Перейти к содержимому
  • 0
WheatComp

Второй модем не активизируется, дает ошибку

Вопрос

В одном компьютере установлены 1 проводной и 1 беспроводной модемы. Через проводной данные принимаются, а через беспроводной отсылаются данные рою из роботов. Каждый модем работает в разное время, с разными программами. Сначала запускаю программу для принятия данных через проводной. Закрываю, запускаю программу для беспроводной. В этот момент вылетает ошибка (фото). Каждый модем устанавливается своей отдельной программой как первичный через component.setPrimary("modem", "адрес модема"). После беспроводного программа для проводного запускается нормально, работает.

 

Интересно, что если повторно запустить программу для беспроводного, то все работает, и Primary определяется, и файл отсылается. Вот код:

local component = require("component")

local modem = component.modem

component.setPrimary("modem", "адрес модема") -- пробовал ставить и перед предыдущей строкой.

prim = component.getPrimary("modem").address
  print("primary modem is : "..prim)

 

2.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендуемые сообщения

И при таком коде выдает то же самое (после закрытия программы для проводной карты), при повторном запуске этой же программы для беспроводной карты без изменений работает нормально:

local component = require("component")
local modem = component.modem

if component.isAvailable("modem") == true then
  print("available") 
  component.setPrimary("modem", "a257b9")
  prim = component.getPrimary("modem").address
  print("Primary : "..prim)
else
  print("unavail")
end

Понятно, что он выдает ошибку на 68-й строчке 04_component.lua, не может выполнить get.Primary("modem"), но он же сказал, что isAvailable("modem") == true?

 

2.jpg

Изменено пользователем WheatComp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
5 часов назад, WheatComp сказал:

И при таком коде выдает то же самое (после закрытия программы для проводной карты), при повторном запуске этой же программы для беспроводной карты без изменений работает нормально:

При изучении функции component.setPrimary можно заметить, что главный компонент устанавливается не сразу, а по истечении таймера в 0.1 секунду. Соответственно, если программа переопределяет главный компонент, то перед его использованием следует выполнить задержку не менее 0.1 секунды. Например, так: os.sleep(0.1)

 

И ещё возникает вопрос: а зачем вообще переопределять главный компонент? Адрес нужного компонента уже известен, поэтому можно сразу обращаться к нему, не дёргая лишний раз API и не выдерживая паузу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 час назад, WheatComp сказал:

 


local component = require("component")
local modem = component.modem

if component.isAvailable("modem") == true then
  ...

 

Ты ставишь компонент модема перед тем как проверить есть ли он.
А почему ты используешь примари? component.invoke(addrs, functionName, ...) <-- обращается именно к компоненту addrs, имя функций пишешь в строковом варианте, например:
 

local address = '0ab'
local cmp = require('component')
local address = cmp.get(address) --Получаем полный адрес из скороченого, обезательно
local sides = require('sides')

cmp.invoke(address,'setOutput',sides.up,5)
print(cmp.invoke(address,'getOutput',sides.north))
cmp.invoke(address,'setOutput',sides.down,12)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
8 часов назад, eu_tomat сказал:

И ещё возникает вопрос: а зачем вообще переопределять главный компонент? Адрес нужного компонента уже известен, поэтому можно сразу обращаться к нему, не дёргая лишний раз API и не выдерживая паузу.

Стал заморачиваться с переопределением из-за того, что после закрытия программы для беспроводного модема команда component.getPrimary("modem") выдает адрес беспроводного, соответственно строка modem.broadcast(...) приводит к широкому вещанию проводным модемом (а мне нужно было, чтобы вещал беспроводной). Эта функция - modem.broadcast(...) применима к обоим типам модемов, поэтому выход был логичным - поменять приоритет модемов. Но он оказался не логичным с точки зрения разработчиков. Было бы удобнее, если бы были отдельные типы broadcast-a, например, modem.broadcastWireless(...), который приводил бы к посылке сигнала именно беспроводным модемом. Но так не было сделано. Я вот думаю, может, в лутовой дискете "Network" есть что-то подобное?

Разработчики подложили подводный камень в виде 0.1-секундной задержки и не сообщили об этом в официальном туториале. Ну чтож, их же много было, да и проект некоммерческий, насколько я понял. Может, потом исправят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, Oleshe сказал:

Ты ставишь компонент модема перед тем как проверить есть ли он.

Это разве не логично? Сначала поставил, чтобы было что проверять, а затем проверил.

2 часа назад, Oleshe сказал:

обращается именно к компоненту addrs, имя функций пишешь в строковом варианте, например:

В этом случае работает, как и должно, спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, WheatComp сказал:

Сначала поставил, чтобы было что проверять, а затем проверил.

Смотри: когда ты добавляешь компонент, он уже в компьютере, его не надо определять там что-то с ним делать, система разберётся сразу когда ты его вставишь.

Здесь мы обозначаем модем, предполагается что он уже есть, хотя это не так. Уже после того как мы определили мы проверяем есть ли он, то-есть он у нас либо будет либо ошибка что его нету.
На то и "No primaty 'modem' available" потому-что системе нечего регистрировать как модем и нечего дать программе.


В компьютере нету модема что-бы его дать программе, а isAvailable проверяет есть ли он, то-есть мы проверяем есть ли он, и если есть то уже определяем его. Типа:

local cmp = require('copmonent')
if cmp.isAvailable('modem') then
  local modem = cmp.modem
  print('Есть :)')
else
  print('Нету :(')
end

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, Oleshe сказал:

Смотри: когда ты добавляешь компонент, он уже в компьютере, его не надо определять там что-то с ним делать, система разберётся сразу когда ты его вставишь.

В документации написано, то isAvailable проверяет, есть ли первичный компонент данного типа:

Цитата

component.isAvailable(componentType: string): boolean
Checks if there is a primary component of the specified component type.

Это тоже, конечно же, еще один косяк разработчиков. Надо было написать component.isAvailablePrimary(). То есть эта строка проверяет не просто есть ли модем в системном блоке, а именно наличие первичного модема. Но, как сказал @eu_tomat , (было бы, кстати, любопытно посмотреть, где устанавливается такая пауза), почему-то установлена пауза в 0.1 сек. после команды component.setPrimary().

Я пытался не просто проверить наличие модема в компе, а установить модем, если можно так выразиться, "по-умолчанию". Как, например, с принтерами. В уиндоуз на какой принтер ставишь галочку "По умолчанию", этот принтер и начинает печатать, когда в какой-нибудь программе нажимаешь на кнопку "Печать". А тут у меня после программы, которая принимала данные через проводную сетевую плату, первичной была проводная карта. Но тут, похоже, действительно не надо заморачиваться с первичностью, возможно, дело было в другом. А может, надо. Сейчас разбираюсь с этим вопросом.

Изменено пользователем WheatComp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
53 минуты назад, WheatComp сказал:

было бы, кстати, любопытно посмотреть, где устанавливается такая пауза

В этом месте: https://github.com/MightyPirates/OpenComputers/blob/af2db43c53b9690fceabfb813987572bf2258db5/src/main/resources/assets/opencomputers/loot/openos/boot/04_component.lua#L104-L108

function component.setPrimary(componentType, address)
  ...
        timer=event.timer(0.1, function()
          adding[componentType] = nil
          primaries[componentType] = primary
          computer.pushSignal("component_available", componentType)
        end)

 

В 21.05.2023 в 19:45, WheatComp сказал:

В одном компьютере установлены 1 проводной и 1 беспроводной модемы. Через проводной данные принимаются, а через беспроводной отсылаются данные рою из роботов. Каждый модем работает в разное время, с разными программами. Сначала запускаю программу для принятия данных через проводной. Закрываю, запускаю программу для беспроводной. В этот момент вылетает ошибка (фото). Каждый модем устанавливается своей отдельной программой как первичный через component.setPrimary("modem", "адрес модема").

Предлагаю рассмотреть другой вариант решения задачи. Так как сетевых плат всего две, а их типы различны, то можно отказаться не только от манипуляций с главным компонентом, но и от запоминания адресов. Например, так:

local component = require"component"

local wireless_modem_required = true
local modem

for addr in component.list"modem" do
  if component.invoke(addr,"isWireless") == wireless_modem_required then
    modem = component.proxy( addr )
    break
  end
end

if modem then
  print( modem.address )
  modem.broadcast( 1, "success" )
end

Значение переменной wireless_modem_requiredв этом коде задаёт тип сетевой платы: проводной или беспроводной.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
17 часов назад, eu_tomat сказал:

Предлагаю рассмотреть другой вариант решения задачи.

Хорошая реализация. Похоже, нужно будет делать так. Почему?

Вчера провел эксперимент. 2 компа, в одном 2 карты 2-х разных типов (назовем хост), в другом только проводная карта, 1 робот с беспроводной картой. Все команды на всех устройствах вводил через интерпретатор lua. В роботе и в не-хост компе запустил =event.pull("m"). C хоста ввел modem.broadcast(123, "message"). Не-хост компьютер получил сообщение, а в роботе так и висит =event.pull("m"). Он должен быть получить сообщение, потому что modem.broadcast же выполняется на всех двух картах? На хосте проверил getPrimary("modem"), оказалось, что стоит проводной модем. Поменял primary на беспроводной модем (setPrimary) - в этом случае сообщение получают оба устройства: и не-хост компьютер, и робот. Проделал это все 2 раза с тем же результатом.

 

А вот не-хост компьютер получает сообщение в любом случае, неважно, какая карта стоит в primary в хосте. Даже если сделать broadcast во время, когда в primary хоста стоит беспроводная карта, не-хост все равно получает сообщение, и показывает адрес беспроводной карты (в поле, где указан адрес карты-отправителя), хотя у него не установлена беспроводная карта! Если вверху, где подчеркнуто, то почему же здесь не так же (то есть не-хост не должен был получать сообщение)?

 

В общем, не совсем ясно, для чего именно служит Primary модемов, в документации об этом мало сказано. Предполагаю, для использования в первую очередь. Тогда непонятно, почему же разный результат для модемов разного типа. Но, очевидно, при применении беспроводной карты (в случае, если в компе 2 разных карт) нужно как-нибудь обрабатывать эту особенность, можно через Ваш код, можно через invoke прямо прописав адрес карты.

Изменено пользователем WheatComp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 минуту назад, WheatComp сказал:

Он должен быть получить сообщение, потому что modem.broadcast же выполняется на всех двух картах?

Широковещательное сообщение может быть принято любой сетевой платой с открытым портом-адресатом при наличии среды передачи (либо при подключении кабелем, либо нахождении в зоне действия беспроводного сигнала).

 

15 минут назад, WheatComp сказал:

аже если сделать broadcast во время, когда в primary хоста стоит беспроводная карта, не-хост все равно получает сообщение, и показывает адрес беспроводной карты (в поле, где указан адрес карты-отправителя), хотя у него не установлена беспроводная карта!

Беспроводную сетевую плату можно рассматривать как улучшенный вариант обычной проводной платы, т.к. она сохраняет возможность проводной связи.

 

18 минут назад, WheatComp сказал:

не совсем ясно, для чего именно служит Primary модемов, в документации об этом мало сказано.

Главный компонент нужен лишь для упрощения подключения компонента. Если главный компонент назначен, то для его подключения достаточно лишь выполнить что-то вроде modem = component.modem. В противном случае приходится использовать более длинный вариант кода с component.list("modem").

 

22 минуты назад, WheatComp сказал:

можно через invoke

Нет принципиальной разницы в работе с компонентами через component.invoke или component.proxy.

component.proxy удобнее для программиста, и является высокоуровневым API для component.invoke.

component.invokeчуть меньше нагружает компьютер, а также доступен из EEPROM, т.к. является низкоуровневым интерфейсом.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, eu_tomat сказал:

Широковещательное сообщение может быть принято любой сетевой платой с открытым портом-адресатом при наличии среды передачи

Значит, дело в беспроводной карте хоста? Если беспроводная карта не primary, то она не отсылает сообщение.

  

2 часа назад, eu_tomat сказал:

Беспроводную сетевую плату можно рассматривать как улучшенный вариант обычной проводной платы, т.к. она сохраняет возможность проводной связи.

Хотел бы уточнить, что это касается беспроводной карты 2-го уровня, 1-го уровня карта не поддерживает проводную связь.

Изменено пользователем WheatComp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
17 минут назад, WheatComp сказал:

Значит, дело в беспроводной карте хоста? Если беспроводная карта не primary, то она не отсылает сообщение.

Зависит от кода программы. Если выбирать сетевую карту кодом modem = component.modem, то будет выбран именно главный компонент. И если им является проводная карта, то сообщение по беспроводному каналу не будет послано.

 

Но если выбирать сетевую карту по её адресу, то главный компонент не будет играть какой-либо роли. При этом не имеет значения, как мы получим адрес компонента: введём ли его вручную или же определим перебором, проверяя нужное свойство сетевой платы.

 

@WheatComp Кстати, я думаю, что в описанной задаче вообще не нужна проводная плата, т.к. и беспроводная точно также обеспечивает передачу по проводам. Если требуется заблокировать передачу по воздуху, можно уменьшить до минимума мощность передатчика кодом modem.setStrength(0). Или можно использовать разные номера портов для передачи по проводам и по воздуху.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, eu_tomat сказал:

Если выбирать сетевую карту кодом modem = component.modem, то будет выбран именно главный компонент. И если им является проводная карта, то сообщение по беспроводному каналу не будет послано.

Вот-вот, это тот подводный камень, об который я споткнулся. Главное - об этом в туториале ни слова. Сколько таких подводных камней впереди - неизвестно...

2 часа назад, eu_tomat сказал:

Кстати, я думаю, что в описанной задаче вообще не нужна проводная плата, т.к. и беспроводная точно также обеспечивает передачу по проводам.

Да, оказывается можно обойтись без проводной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 23.05.2023 в 23:26, eu_tomat сказал:

Если выбирать сетевую карту кодом modem = component.modem, то будет выбран именно главный компонент. И если им является проводная карта, то сообщение по беспроводному каналу не будет послано.

А не баг ли это? Если это баг, то может, кто-то c хорошим английским возьмется issue сделать на страничку мода?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 минуты назад, WheatComp сказал:

А не баг ли это?

А почему это баг-то?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

@eu_tomat Потому что если главным компонентом выбрана беспроводная карта, то сообщение будет послано и беспроводной, и проводной картой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 минуту назад, WheatComp сказал:

@eu_tomat Потому что если главным компонентом выбрана беспроводная карта, то сообщение будет послано и беспроводной, и проводной картой.

Беспроводная карта может послать сообщение одновременно по проводному и беспроводному каналу, это нормально. Вторая карта (проводная) никаких сообщений не посылает, если её об этом не просят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Значит, если в сист. блоке 2 карты, то одна из них никак не участвует в передаче сообщений, посланных обычным способом, без выбирания через адрес? А только главный модем работает. Вот в чем дело, понятно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...