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


Фотография

bios-net для централизованного управления сетью контроллеров/дронов/роботов/компьютеров

ComputerCraft BIOS EEPROM network

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 15

#1 Оффлайн   swg2you

swg2you
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 14 Июнь 2015 - 22:03

Привет all. (после публикации заметил ошибку в названии темы и тегах, код для OpenComputers а не для ComputerCraft, я их постоянно путаю)

 

код 204 байта:

_=component;m=_.proxy(_.list('modem')())m.open(7)u=table.unpack::r::e={computer.pullSignal()}if e[1]=='modem_message'then;_={load(e[6])}if _[1]then;_={pcall(_[1],u(e,7))}end;m.send(e[3],7,u(_));end;goto r

или код 231 байт:

::r::pcall(load("_=component;m=_.proxy(_.list('modem')())m.open(7)u=table.unpack::r::e={computer.pullSignal()}if e[1]=='modem_message'then;_={load(e[6])}if _[1]then;_={pcall(_[1],u(e,7))}end;m.send(e[3],7,u(_));end;goto r"));goto r

Записать в EEPROM любого устройства имеющего сетевую карту, и включить устройство.

 

На отдельном компьютере выполняющем роль сервера выполнить код примера:

modem.open(7)
modem.broadcast(7, "return 'Hello ',  _VERSION,  ...", true, 42, 'bebebe')

Прочитать ответ от модема, и понять что произошло.

=============================================

Дополнительные примеры:

  1. broadcast(7, 'bebebe')
  2. broadcast(7, 'bebebe()')
  3. broadcast(7, 'return {}') 
  4. broadcast(7, true)
  5. broadcast(7)
  6. broadcast(7, 'return computer.pullSignal()' )
  7. code=[[ --my super puper long program nice code ]]; broadcast(7, сode)
  8. broadcast(7, 'component.proxy(component.list("eeprom")()).set(...)', codeforflashing)
  9. и прочие извращения

1,2 покажут обработку ошибок на стадии компиляции и выполнения; 3,4,5 покажут различие в коде 204 и 231 и ограничения передачи данных; 6,... - некоторые возможности

 

Для самых бегемотов:

  1. Можно Хранить код 204 в setData
  2. Можно добавить аутентиикацию, чтоб вражина за стенкой не broadcast-ил нам тут с планшета
  3. Можно построить SCADA-систему из дронов, роботов, контроллеров и компьютеров.
  4. Что-то еще...

ЗЫ

mods/OpenComputers-MC1.7.10-1.5.12.26-universal.jar

примеры не проверял, писал здесь сходу.


Сообщение отредактировал swg2you: 14 Июнь 2015 - 22:42

  • Alex и eu_tomat это нравится

#2 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 15 Июнь 2015 - 00:06

::
Вот это - явно какое то шаманство и запрещенные техники. Я такого еще никогда за 2 года программирования на Lua не видел.

 

А по теме - для биосов что только не делали. Даже превращали его в жесткий диск, переписывая прямо исходник биоса.

Твоя программа полезная, но не новая.

 

Кстати, твой код всё еще можно уменьшить не изменив функционал.



#3 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 15 Июнь 2015 - 00:13

>Вот это - явно какое то шаманство и запрещенные техники. Я такого еще никогда за 2 года программирования на Lua не видел.

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

 

>Кстати, твой код всё еще можно уменьшить не изменив функционал.

А вот здесь поподробней пожалуйста.


Сообщение отредактировал swg2you: 15 Июнь 2015 - 01:12


#4 Оффлайн   Doob

Doob
  • Пользователи
  • Сообщений: 814
  • Уровень сигнала: 19,57%
  • В игре: 146 час. 10 мин.

Награды

                                   

Отправлено 15 Июнь 2015 - 08:35

>Кстати, твой код всё еще можно уменьшить не изменив функционал.
А вот здесь поподробней пожалуйста.

 
Например, 157 байт
m=component.proxy(component.list('modem')()) m.open(42) while true do e,_,_,_,_,cmd=computer.pullSignal() if e=='modem_message' then pcall(load(cmd)) end end

Сообщение отредактировал Doob: 15 Июнь 2015 - 08:36


#5 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Гуру
  • Сообщений: 1 228
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

   5                              

Отправлено 15 Июнь 2015 - 12:00

>Вот это - явно какое то шаманство и запрещенные техники. Я такого еще никогда за 2 года программирования на Lua не видел.

Не разочаровывай меня, это же основы языка.

А в самом деле, не сочти за труд, объясни что это за операторы :: и goto. Я, конечно догадываюсь, что это определение метки и переход по метке, но в Луа с таким сталкиваюсь впервые.



#6 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 15 Июнь 2015 - 12:42

А в самом деле, не сочти за труд, объясни что это за операторы :: и goto. Я, конечно догадываюсь, что это определение метки и переход по метке, но в Луа с таким сталкиваюсь впервые.

На английском, но с примерами есть тут:

http://lua-users.org...i/GotoStatement

 

 

 

>>здесь главное форма реализации,

>>Мой код умеет так же, но он намного более компактный

Можно вопрос - а зачем? Зачем тебе такой компактный код? В биосе 4к места, почему бы им не воспользоваться?

 

 

 

>>А вот здесь поподробней пожалуйста.

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

 

  • Твой код написан хорошо, и абсолютно без изменения функционала удалось сжать его всего на 4-10 символов.
  • С небольшими изменениями, которые не отразятся на условиях работы программы при 90% случаев, можно сжать 230 вариант примерно до 150 байт
    В принципе можно остановиться на этом варианте, но я пошел дальше.
  • Если отказаться от входных параметров, которые не нужны, так как их можно реализовать в клиентской программе, можно сжать первый вариант до 130 байт
  • Если добавить еще небольших условностей, типа без проверки на сигнал модема, можно сжать код до 107 байт
  • Если отказаться от отсылки сообщений об ошибках обратно, которые можно и так определить первым сообщением, код получается 92 байта

Сообщение отредактировал Krutoy: 15 Июнь 2015 - 12:44

  • swg2you это нравится

#7 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Гуру
  • Сообщений: 1 228
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

   5                              

Отправлено 15 Июнь 2015 - 12:54

 

На английском, но с примерами есть тут:

http://lua-users.org...i/GotoStatement

 

Первый же пример выдал

bios:338: [string "test"]:7: '=' expected

Нет в Minecraft-Lua безусловных переходов, похоже. (тестировалось под КК)



#8 Оффлайн   MineUbuntu

MineUbuntu
  • Пользователи
  • Сообщений: 185
  • Уровень сигнала: 4,76%
  • В игре: 35 час. 33 мин.

Награды

     

Отправлено 15 Июнь 2015 - 13:04

goto есть зло сущее, отродье BASIC'овское, не используйте его, да не проклятыми за баги будете.

#9 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 15 Июнь 2015 - 13:15

goto есть зло сущее, отродье BASIC'овское, не используйте его, да не проклятыми за баги будете.

Это предубеждение. Хочу заметить, что goto было добавлено в версию 5.2 совсем не давно, и значит, никак не является архаизмом.

И между прочим, это может быть очень удобно, например, из за отсутствия в луа оператора continue.



#10 Оффлайн   Doob

Doob
  • Пользователи
  • Сообщений: 814
  • Уровень сигнала: 19,57%
  • В игре: 146 час. 10 мин.

Награды

                                   

Отправлено 15 Июнь 2015 - 13:18

Первый же пример выдал

bios:338: [string "test"]:7: '=' expected

Нет в Minecraft-Lua безусловных переходов, похоже. (тестировалось под КК)

 

В OpenComputers все работает

Вызов функции это тоже безусловный переход

 

 

На английском, но с примерами есть тут:

http://lua-users.org...i/GotoStatement

 

 

 

>>здесь главное форма реализации,

>>Мой код умеет так же, но он намного более компактный

Можно вопрос - а зачем? Зачем тебе такой компактный код? В биосе 4к места, почему бы им не воспользоваться?

 

 

 

>>А вот здесь поподробней пожалуйста.

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

 

  • Твой код написан хорошо, и абсолютно без изменения функционала удалось сжать его всего на 4-10 символов.
  • С небольшими изменениями, которые не отразятся на условиях работы программы при 90% случаев, можно сжать 230 вариант примерно до 150 байт
    В принципе можно остановиться на этом варианте, но я пошел дальше.
  • Если отказаться от входных параметров, которые не нужны, так как их можно реализовать в клиентской программе, можно сжать первый вариант до 130 байт
  • Если добавить еще небольших условностей, типа без проверки на сигнал модема, можно сжать код до 107 байт
  • Если отказаться от отсылки сообщений об ошибках обратно, которые можно и так определить первым сообщением, код получается 92 байта

 

 

Да ты маг, у меня только 108, что сжать еще, не знаю))


Сообщение отредактировал Doob: 15 Июнь 2015 - 13:22


#11 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 15 Июнь 2015 - 21:43

 
Применение бесконечного цикла на goto позволяет сэкономить 5-6 байт, сравните длины:
::L::a={}goto L
while a={}true do end
repeat a={}until nil

Тем кому религия не позволяет пользоваться goto, хочу напомнить, что абсолютно все виды циклов, в конечном итоге, строятся на основе переходов.

---
Размер не важен, если кроме этого кода в EEPROM больше ничего не нужно. Но если вы будете писать, к примеру, дрона с серьезной логикой, или операционную систему работающую из чипа, или интеллектуальный загрузчик с встроенным файловым менеджером, просмотром окружения и доступных устройств, то в 4к вам будет тесновато, и блок, добавляющий возможность выполнения присланного по сети кода, удаленной перепрошивки и прочего - должен быть как можно меньше.
 
На самом деле, это просто получение удовольствие от стремления к идеалу. Спортивный интерес, если угодно. 
---
>без изменения функционала удалось сжать его всего на 4-10 символов.
>Если отказаться от отсылки сообщений об ошибках обратно, которые можно и так определить первым сообщением, код получается 92 байта
Моя хотеть созерцать эту красоту.
 
upd:
Хотя нет! Моя хотеть достичь этой красоты самостоятельно.
 
upd2:
Нет предела совершенству.
Если поставить задачу: в бесконечном цикле, не проверяя на сигнал модема, не обрабатывая ошибок, выполнять полученный по сети код то можно уместиться в 90 байт.

Сообщение отредактировал swg2you: 15 Июнь 2015 - 23:46

  • Doob это нравится

#12 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 16 Июнь 2015 - 07:42

Если поставить задачу: в бесконечном цикле, не проверяя на сигнал модема, не обрабатывая ошибок, выполнять полученный по сети код то можно уместиться в 90 байт.
Молодец. Значит таки можешь.

Вот мой код в 92 байта (добавлены переходы строки для читабельности):

_=component
_.proxy(_.list'od'()).open(7)
::r::
pcall(load(({computer.pullSignal()})[6]))
goto r

А так же код с возвращением ошибки и с проверкой имени сигнала. Обрати внимание как я проверяю название сигнала:

-- # Проверка сигнала
_=component m=_.proxy(_.list'od'())m.open(7)::r::a,_,c,_,_,f=computer.pullSignal()_=a:find"mo"and m.send(c,7,pcall(load(f)))goto r

-- # Возврат ошибки
_=component m=_.proxy(_.list'od'())m.open(7)::r::m.send(c,7,pcall(load(({computer.pullSignal()})[6]))goto r

Но тут появилась идея что в принципе, если инициализировать контроллер\дрон первым сообщением, можно сократить до 75 байт:

_=component _.proxy(_.list'od'()).open(7)load(({computer.pullSignal()})[6])

Теперь показывай свое на 90



#13 Оффлайн   Zer0Galaxy

Zer0Galaxy
  • Гуру
  • Сообщений: 1 228
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

   5                              

Отправлено 16 Июнь 2015 - 11:24

Предлагаю добавить swg2you в белый список, как проявившего серьезный интерес к программированию на Луа.



#14 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 16 Июнь 2015 - 13:05

Предлагаю добавить swg2you в белый список, как проявившего серьезный интерес к программированию на Луа.

Моя интуиция подсказывает что swg2you интерес к Lua уже давно проявил. Похоже он где то еще вне майна Луа выучил.

Это так?



#15 Оффлайн   swg2you

swg2you
  • Автор темы
  • Пользователи
  • Сообщений: 268
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 16 Июнь 2015 - 16:16


Теперь показывай свое на 90

Ва-а! Я даже не думал что так ({})[i] можно обратиться к элементу таблицы.
В своем, я перенес метку в другое место, что сэкономило один байт на разделителе, и выбросил pcall.
--код 90 байт:
--C=component::R::C.proxy(C.list('od')()).open(7)E={computer.pullSignal()}load(E[6])()goto R


--он же развернутый:
C=component
::R::
C.proxy(C.list('od')()).open(7)
E={computer.pullSignal()}
load(E[6])()
goto R

Если применить твой метод обращения к элементу таблицы, то можно сократить до 89 байт, но такие сокращения годятся только для разминки мозга, на практике этот код нестабилен, любое "неправильное" событие приведет к ошибке.

 
>Обрати внимание как я проверяю название сигнала: _=a:find"mo"and m.send()
красота в чистом виде, такие конструкции меня всегда приводят в восторг
 
 >если инициализировать контроллер\дрон первым сообщением
Выбросить цикл и не проверять "правильность" события можно, но я пошел по другому пути.
===
Код для EEPROM в 94 байта полностью сохраняющий функционал:
--код 94 байта:
C=component::R::C.proxy(C.list('od')()).open(7)E={computer.pullSignal()}load(E[9]or'')()goto R

--он же в развернутом виде, с комментариями:
C=component

::R:: 
--метка в этом месте экономит 1 байт, т.к. служит одновременно разделителем соседних участков

C.proxy(C.list('od')()).open(7) 
--а то что мы будем открывать уже открытый порт - не является исключением и вполне допустимо

E={computer.pullSignal()} 
--параметры события будем сохранять поскольку мы будем их использовать в загружаемом коде

load(E[9]or'')()
--Если у нас возникло событие вернувшее 9-й параметр, то это наше событие, иначе выполняем пустоту ''

--Стандартные события возвращают не больше 6-ти параметров, а если говорить о сетевых, то
--маловероятно, что кто-то будет делать broadcast с таким количеством параметров. 
--broadcast(port, mess1, mess2, mess3, mess4) <--такое маловероятно, но если встретится,
--то ничто нам не помешает, пожертвовав одним байтом сдвинуть позицию еще дальше.
--Поэтому "правильность" события будем кодировать позиционным методом. 

goto R

Теперь у нас есть сверх-компактный код хранимый в EEPROM, и нам осталось обеспечить обработку ошибочных ситуаций. Поскольку даже самая простая планка ОЗУ имеет в 48 раз больший объем чем EEPROM (192к против 4к), то вполне логичным шагом будет перенос обработки исключений в оперативную память.

 
Напишем конверт обеспечивающий безопасную компиляцию/выполнение кода пользователя и возврат результата или сообщения об ошибке:
U = table.unpack

R = {load(E[10])}
--10-й параметр события загружаем как код пользователя
--конечно, можно заключать код пользователя в конверт простой конкатенцией строк, но такая методика 
--порождает "проблему кавычек" и может приводить к ошибкам, поэтому конверт отдельно, код отдельно

if R[1] then 
  R = { pcall( R[1], U(E, 11) ) } --
end
--если компиляция успешна пробуем выполнить чанк передав ему все оставшиеся параметры

C.proxy(C.list('od')()).send(E[3], 7, U(R))
--и возвращаем отправителю результаты или ошибку если при компиляции/выполнении возникли проблемы

Теперь свернем код конверта, напишем функцию выполняющую код пользователя на удаленных устройствах, и попробуем с ней поиграть.

 
Длиннокод с длиннокомментариями:
local wrap="U=table.unpack;R={load(E[10])}if R[1]then;R={pcall(R[1],U(E,11))}end;C.proxy(C.list('od')()).send(E[3],7,U(R))"
--конверт объявляем снаружи, мало ли где еще пригодится

function enetRun(addr, code, ...)
  local result=false  
  if type(code)=='string' then
  --load() в eeprom должен получать только строки  
    if addr then
      --приемник должен генерировать событие вида 
      --E=={'modem_message', rAddr, sAddr, port, dist, nil, nil, nil, wrap, code, ...}
      --    ^1               2      3      4     5     6    7    8    9     10    11
      --поэтому посылаем конверт, код и параметры начиная с 9-й позиции события
      result=modem.send(addr, 7, nil, nil, nil, wrap, code, ...)
      --                         ^6   7    8    9     10    11
    else
      --если адрес получателя не задан, то отправляем всем желающим
      result=modem.broadcast(7, nil, nil, nil, wrap, code, ...)
    end
  end
  --и возвращаем true если получилось отправить
  return result
end

--теперь попробуем что-то поотправлять:
enetRun(nil, 123) --это не пропустит наша функция

enetRun(nil, 'computer.beep(440)')
--это просто выполнится в удаленном устройстве, пискнет там нотой Ля и вернет: true
--теперь мы сможем организовывать концерты контроллеров и дронов с солистом роботом

enetRun(nil, 'return 123+...', 4)
--это выполнится  и вернет нам: true, 127

enetRun(nil, 'q')
--это отправится, но наш конверт вернет нам: nil, "и текст ошибки компиляции"

enetRun(nil, 'q()')
--это тоже отправится, но конверт вернет нам: false, "текст ошибки выполнения"

--теперь мы можем удаленно выполнять свои хелловорлды
enetRun(nil, 'return "Hello world"')

--передавая им строковые, числовые, nil-ы или булевы параметры
enetRun(nil, 'return ...', 'Hi', nil, true)

--но даже не пытайтесь передать больше 3-х параметров: 
--enetRun(nil, 'return ...', 1, 2, 3, 4) - на это modem.send будет ругаться: false packet has too many parts
--мы ведь передаем 3 nil-а, конверт и код, это уже 5, а modem.send, по видимому, умеет не больше восьми

--также не пытайтесь передавать другие типы данных: таблицы, потоки,  и т.п.
--enetRun(nil, 'return ...', {}) - modem.send обругает вас: false unsupported data type

--возврат "неправильных" данных вызывающий ошибку на стороне удаленного устройства оставим на совести пользователей  
--enetRun(nil, 'return {}') - треш, краш и халт в modem.send удаленного устройства
--но, если очень захочется, то send конверта можно заключить в pcall, чтобы красиво обработать и это исключение

--осталось получить все что нам прислали наши контродроботы
repeat
  local e={computer.pullSignal()}; 
  e[2]=tostring(e[2]):sub(1,3)  --обрезав адреса до 3-х символов
  e[3]=tostring(e[3]):sub(1,3)  
  prn(table.unpack(e))
until e[1]=='key_up' 
--и выйти по аникею пропищав напоследок Си
computer.beep(329.6)

--напомню, что enetRun(addr, '') будет обращаться к конкретному устройству
--а enetRun(nil, '') позволить опросить все доступные, чтобы выбрать любимчика

--ах, да, prn() это моя собственная функция вывода, у меня нет OpenOS, пишите там print
--и не забывайте вначале получить экземпляр модема и открыть 7-й порт, чтобы видеть ответы

На этом пока всё, спасибо всем отписавшимся, и отдельное спасибо Krutoy за повышение планки и наталкивание на идеи.

 

ЗЫ

Интуиция подводит. С Lua я играю всего пару недель и исключительно через СС OC, хотя кодер довольно опытный, однопроходные дизассемблеры для зилоговских процессоров еще в начале 90-х писал. Потом были бейсики с паскалями, потом LD, FBD, SFC и паскалеподобный ST в разных скадах и плк. Потом кодить бросил и переквалифицировался, а сейчас вот увлекся и трясу стариной, чтоб мозги не сильно ржавели.

 



#16 Оффлайн   Krutoy

Krutoy
  • Гуру
  • Сообщений: 499
  • Уровень сигнала: 0%
  • В игре: 0 час. 0 мин.

Награды

              

Отправлено 17 Июнь 2015 - 09:40

ЗЫ Интуиция подводит. С Lua я играю всего пару недель и исключительно через СС OC, хотя кодер довольно опытный, однопроходные дизассемблеры для зилоговских процессоров еще в начале 90-х писал. Потом были бейсики с паскалями, потом LD, FBD, SFC и паскалеподобный ST в разных скадах и плк. Потом кодить бросил и переквалифицировался, а сейчас вот увлекся и трясу стариной, чтоб мозги не сильно ржавели.
Я так и знал - что то тут не чисто  :)

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

 

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

http://computercraft...ge-6#entry10751

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







Темы с аналогичным тегами ComputerCraft, BIOS, EEPROM, network

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных