|
| 1 | +# migration script for Shelly |
| 2 | + |
| 3 | +# simple function to copy from autoconfig archive to filesystem |
| 4 | +# return true if ok |
| 5 | +def cp(from, to) |
| 6 | + import path |
| 7 | + if to == nil to = from end # to is optional |
| 8 | + if !path.exists(to) |
| 9 | + try |
| 10 | + # tasmota.log("f_in="+tasmota.wd + from) |
| 11 | + var f_in = open(tasmota.wd + from) |
| 12 | + var f_out = open(to, "w") |
| 13 | + var f_content = f_in.readbytes(0x2000) # read by chunks of 8kb |
| 14 | + while size(f_content) > 0 |
| 15 | + f_out.write(f_content) |
| 16 | + f_content = f_in.readbytes(0x2000) # read next chunk |
| 17 | + end |
| 18 | + f_in.close() |
| 19 | + f_out.close() |
| 20 | + except .. as e,m |
| 21 | + tasmota.log("OTA: Couldn't copy "+to+" "+e+" "+m,2) |
| 22 | + return false |
| 23 | + end |
| 24 | + return true |
| 25 | + end |
| 26 | + return true |
| 27 | +end |
| 28 | + |
| 29 | +def copy_ota(from_addr, to_addr, sz) |
| 30 | + import flash |
| 31 | + import string |
| 32 | + var size_left = sz |
| 33 | + var offset = 0 |
| 34 | + |
| 35 | + tasmota.log(string.format("UPL: Copy flash from 0x%06X to 0x%06X (size: %ikB)", from_addr, to_addr, sz / 1024), 2) |
| 36 | + while size_left > 0 |
| 37 | + var b = flash.read(from_addr + offset, 4096) |
| 38 | + flash.erase(to_addr + offset, 4096) |
| 39 | + flash.write(to_addr + offset, b, true) |
| 40 | + size_left -= 4096 |
| 41 | + offset += 4096 |
| 42 | + if ((offset-4096) / 102400) < (offset / 102400) |
| 43 | + tasmota.log(string.format("UPL: Progress %ikB", offset/1024), 3) |
| 44 | + end |
| 45 | + end |
| 46 | + tasmota.log("UPL: done", 2) |
| 47 | +end |
| 48 | + |
| 49 | +# make some room if there are some leftovers from shelly |
| 50 | +import path |
| 51 | +path.remove("index.html.gz") |
| 52 | + |
| 53 | +# copy some files from autoconf to filesystem |
| 54 | +var ok |
| 55 | +ok = cp("bootloader-tasmota-c3.bin") |
| 56 | +ok = cp("Partition_Wizard.tapp") |
| 57 | + |
| 58 | +# use an alternative to partition_core that can read Shelly's otadata |
| 59 | +tasmota.log("OTA: loading "+tasmota.wd + "partition_core_shelly.be", 2) |
| 60 | +load(tasmota.wd + "partition_core_shelly.be") |
| 61 | + |
| 62 | +# load bootloader flasher |
| 63 | +tasmota.log("OTA: loading "+tasmota.wd + "bootloader.be", 2) |
| 64 | +load(tasmota.wd + "bootloader.be") |
| 65 | + |
| 66 | + |
| 67 | +# all good |
| 68 | +if ok |
| 69 | + # do some basic check that the bootloader is not already in place |
| 70 | + import flash |
| 71 | + if flash.read(0x1000, 4) == bytes('CD3F6395') |
| 72 | + tasmota.log("OTA: bootloader already in place, not flashing it") |
| 73 | + else |
| 74 | + ok = global.bootloader().flash("bootloader-tasmota-c3.bin") |
| 75 | + end |
| 76 | + if ok |
| 77 | + var p = global.partition_core_shelly.Partition() |
| 78 | + var app0 = p.get_ota_slot(0) |
| 79 | + var app1 = p.get_ota_slot(1) |
| 80 | + var app0_size = app0.get_image_size() |
| 81 | + var app1_size = app1.get_image_size() |
| 82 | + # check if we get some Tasmota signature in slot 1 |
| 83 | + if (flash.read(p.get_ota_slot(1).start + 16, 4) == bytes("00FFFF00")) |
| 84 | + copy_ota(app1.start, app0.start, app1_size) |
| 85 | + elif (flash.read(p.get_ota_slot(0).start + 16, 4) == bytes("00FFFF00")) |
| 86 | + copy_ota(app0.start, app1.start, app0_size) |
| 87 | + end |
| 88 | + var otadata_offset = p.otadata.offset |
| 89 | + flash.erase(otadata_offset, 0x2000) |
| 90 | + tasmota.log("OTA: Shelly migration successful", 2) |
| 91 | + end |
| 92 | +end |
| 93 | + |
| 94 | +# dump logs to file |
| 95 | +var lr = tasmota_log_reader() |
| 96 | +var f_logs = open("migration_logs.txt", "w") |
| 97 | +var logs = lr.get_log(2) |
| 98 | +while logs != nil |
| 99 | + f_logs.write(logs) |
| 100 | + logs = lr.get_log(2) |
| 101 | +end |
| 102 | +f_logs.close() |
| 103 | + |
| 104 | +# Done |
0 commit comments