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