diff --git a/src/application/gateway-node/autoexec.be b/src/application/gateway-node/autoexec.be index 171c72973217e3d4a058a9a54ca88a42c310fae5..2c45aabdf0169aca3ba1482541ecb32df4d799df 100644 --- a/src/application/gateway-node/autoexec.be +++ b/src/application/gateway-node/autoexec.be @@ -133,12 +133,13 @@ def wait_otaconf_finished() mesh_init() end + util.set_wakeup_led(1) + collect_sensor_data() end def wakeup_task() disable_deepsleep() - util.set_wakeup_led(1) wait_otaconf_finished() end diff --git a/src/otaconf/gateway-node/autoexec.be b/src/otaconf/gateway-node/autoexec.be index 5961a152db78453825e328cb7d17d0d2a5abc6d2..06b8d7b0afbe2fb1ad2786dae379f472c477d00a 100644 --- a/src/otaconf/gateway-node/autoexec.be +++ b/src/otaconf/gateway-node/autoexec.be @@ -3,17 +3,31 @@ import json import otaconf import persist import mesh +import path +import string +import re var otaconf_finished = false var _otaconf_timer_id = 'otaconf_timer' +var _file_transfer_timer_id = 'file_transfer_timer' var _wifi_used = tasmota.cmd('Wifi')['Wifi'] == 'ON' var _mesh_scan_retries = 3 var _configuration_uuid = nil var _configuration_files = nil var _configuration_commands = nil +var _own_file = nil +var _current_chunk = nil +var _current_chunk_id = 0 +var _last_chunk_id = 0 +var _file_uuid_in_process = nil +var _file_in_process = nil +var _devices_to_receive_file = {} +var _file_send_retries = 3 var _own_command = nil +var _CHUNK_HEADER_SIZE = 12 + 3 + def _set_ota_conf_interval(cmd, idx, payload) if otaconf.set_poll_interval(payload) @@ -42,7 +56,7 @@ end def _finish_otaconf(early_exit) if !early_exit - persist.last_otaconf_poll = tasmota.rtc()['local'] + persist.otaconf_last_poll = tasmota.rtc()['local'] persist.save() end @@ -93,16 +107,144 @@ def _execute_commands() _update_config_status() end -def _distribute_files() - tasmota.log('OTA: distributing files', 2) +def _send_file_chunk() + tasmota.remove_timer(_file_transfer_timer_id) + + if _configuration_files.size() > 0 + var file = _configuration_files[0] + var uuid = file['uuid'] + + if !_devices_to_receive_file.contains(uuid) || _devices_to_receive_file[uuid].size() == 0 + _configuration_files.remove(0) + + _send_file_chunk() + end + + print('test') + + var mac = _devices_to_receive_file[uuid][0] + + print('anus') + + if _file_in_process == nil + if !path.exists(uuid) + tasmota.log('OTA: file: ' + uuid + ' not found - skip', 2) + + _configuration_files.remove(0) + + _send_file_chunk() + end + + tasmota.log('OTA: opening file: ' + uuid, 2) + + _file_in_process = open(uuid) + _file_send_retries = 3 + _current_chunk_id = 0 + _last_chunk_id = 0 + _current_chunk = _file_in_process.read(mesh.MAX_LEN - _CHUNK_HEADER_SIZE) + + tasmota.log('OTA: sending chunk: ' + str(_current_chunk_id) + ' to: ' + mac, 2) + + var payload = uuid + string.format("%03i", _current_chunk_id) + _current_chunk + print('send payload: ' + payload) + + mesh.send(mac, payload) + else + if _current_chunk_id == _last_chunk_id + _file_send_retries -= 1 + + if _file_send_retries > 0 + tasmota.log('OTA: retry sending chunk: ' + str(_current_chunk_id) + ' to: ' + mac + ', retries left: ' + str(_file_send_retries), 2) + + var payload = uuid + string.format("%03i", _current_chunk_id) + _current_chunk + print('send payload: ' + payload) + + mesh.send(mac, payload) + else + _devices_to_receive_file[uuid].remove(0) + + _file_in_process.close() + _file_in_process = nil + + tasmota.log('OTA: retries exceeded: ' + str(_current_chunk_id) + ' to: ' + mac, 2) + end + else + _current_chunk = _file_in_process.read(mesh.MAX_LEN - _CHUNK_HEADER_SIZE) + + if size(_current_chunk) == 0 + _file_in_process.close() + _file_in_process = nil + + _devices_to_receive_file[uuid].remove(0) + + tasmota.log('OTA: finished transfering file: ' + uuid + ' to: ' + mac, 2) + else + tasmota.log('OTA: sending chunk: ' + str(_current_chunk_id) + ' to: ' + mac, 2) + + var payload = uuid + string.format("%03i", _current_chunk_id) + _current_chunk + print('send payload: ' + payload) + + _last_chunk_id = _current_chunk_id + + mesh.send(mac, payload) + end + end + end + + tasmota.set_timer(2000, _send_file_chunk, _file_transfer_timer_id) + else + _execute_commands() + end +end + +def _initiate_file_transfer() + if _configuration_files.size() > 0 + for file : _configuration_files + var device_macs = file['macs'] + var uuid = file['uuid'] + var name = file['name'] + + tasmota.log('OTA: processing file: ' + uuid, 2) + + var f = open(uuid) + var num_chunks = size(f) / (mesh.MAX_LEN - _CHUNK_HEADER_SIZE) + + if num_chunks == 0 && size(f) > 0 + num_chunks = 1 + end + + if size(f) % (mesh.MAX_LEN - _CHUNK_HEADER_SIZE) != 0 + num_chunks + 1 + end + + f.close() + + for device_mac : device_macs + if device_mac == otaconf.get_mac() + # todo own file + _own_file = file + else + tasmota.log('OTA: initiating file transfer with device: ' + device_mac, 2) + + var payload = {'action': 'TRANSFER_FILE', 'name': name, 'uuid': uuid, 'num_chunks': num_chunks} + + print('send payload: ' + json.dump(payload)) - _execute_commands() + mesh.send(otaconf.format_mac(device_mac), json.dump(payload)) + end + end + end + + tasmota.set_timer(2000, _send_file_chunk, _file_transfer_timer_id) + else + _execute_commands() + end end def _devices_registered() tasmota.remove_timer(_otaconf_timer_id) - _distribute_files() + _initiate_file_transfer() end def _check_devices_registered() @@ -113,7 +255,7 @@ def _check_devices_registered() otaconf.register_devices(unregistered_devices, _devices_registered) tasmota.set_timer(3000, _otaconf_timeout, _otaconf_timer_id) else - _distribute_files() + _initiate_file_transfer() end end @@ -152,7 +294,7 @@ def _process_config(response) if response['configuration'].contains('mesh_scan') && response['configuration']['mesh_scan'] _scan_mesh() else - _distribute_files() + _initiate_file_transfer() end else _finish_otaconf(false) @@ -184,10 +326,10 @@ def _check_cluster_registered() end def _check_otaconf() - var next_otaconf_time = int(persist.find('last_otaconf_poll')) + otaconf.get_poll_interval() + var next_otaconf_time = int(persist.find('otaconf_last_poll')) + otaconf.get_poll_interval() var current_time = tasmota.rtc()['local'] - if !persist.has('last_otaconf_poll') || (current_time > next_otaconf_time) + if !persist.has('otaconf_last_poll') || (current_time > next_otaconf_time) _check_cluster_registered() else var remaining_hours = str((next_otaconf_time - current_time) / 3600) @@ -203,11 +345,43 @@ end def _callback(sender, payload) var recieved_data = json.load(payload) - print(recieved_data) # todo remove - print(mesh.get_peers()) # todo remove + print('receive payload: ' + payload) # todo remove + print('receive size: ' + str(size(payload))) if recieved_data != nil && recieved_data.contains('action') var action = recieved_data['action'] + + if action == 'TRANSFER_FILE' + if recieved_data.contains('uuid') + var uuid = recieved_data['uuid'] + + if _devices_to_receive_file.contains(uuid) + _devices_to_receive_file[uuid].push(sender) + else + _devices_to_receive_file[uuid] = [sender] + end + + print(_devices_to_receive_file) + end + end + elif payload != nil && size(payload) == _CHUNK_HEADER_SIZE + var uuid = payload[0..11] + var chunk_id = payload[12..14] + + print('chunks') + print(chunk_id) + print(_current_chunk_id) + print('chunks') + + if re.match('^[0-9]*$', chunk_id) != nil + print('yey') + if int(chunk_id) == _current_chunk_id + print('update') + _current_chunk_id += 1 + end + + _send_file_chunk() + end end end diff --git a/src/otaconf/sensor-node/autoexec.be b/src/otaconf/sensor-node/autoexec.be index d613f6e030763add51b1b25ea9f026783a7df3ed..12c128ac4fc952db6b0979042051bc25f07b017f 100644 --- a/src/otaconf/sensor-node/autoexec.be +++ b/src/otaconf/sensor-node/autoexec.be @@ -42,17 +42,16 @@ def _check_file_transfer_finished(uuid) end def _store_chunk(payload) - print('_store_chunk' + payload) var uuid = payload[0..11] var chunk_id = payload[12..14] var file = open(uuid + '_' + chunk_id + '.part', 'w') - file.write(payload[15..mesh.max_packet_size()]) + file.write(payload[15..mesh.MAX_LEN]) file.close() end def _callback(sender, payload) - print(payload) + print('receive payload: ' + payload) var recieved_data = json.load(payload) if recieved_data != nil && recieved_data.contains('action') @@ -64,14 +63,16 @@ def _callback(sender, payload) tasmota.cmd(recieved_data['command']) elif action == 'TRANSFER_FILE' if recieved_data.contains('name') && recieved_data.contains('uuid') && recieved_data.contains('num_chunks') - _files_in_process[recieved_data['uuid']] = {'name': recieved_data['name'], 'num_chunks': recieved_data['num_chunks'] } + _files_in_process[recieved_data['uuid']] = {'name': recieved_data['name'], 'num_chunks': recieved_data['num_chunks']} - mesh.send(sender, json.dump({'action': 'TRANSFER_FILE'})) + print('send payload: ' + json.dump({'action': 'TRANSFER_FILE', 'uuid': recieved_data['uuid']})) + + mesh.send(sender, json.dump({'action': 'TRANSFER_FILE', 'uuid': recieved_data['uuid']})) end elif action == 'MESH_SCAN' mesh.send(sender, json.dump({'action': 'MESH_SCAN'})) end - elif payload != nil && size(payload) > _CHUNK_HEADER_SIZE + elif payload != nil && size(payload) >= _CHUNK_HEADER_SIZE var uuid = payload[0..11] var chunk_id = payload[12..14] @@ -79,6 +80,8 @@ def _callback(sender, payload) _store_chunk(payload) _check_file_transfer_finished(uuid) + print('send payload: ' + payload[0..14]) + mesh.send(sender, payload[0..14]) end end