esp_alox/goTool/ota.go
2026-03-21 15:11:14 +01:00

137 lines
3.2 KiB
Go

package main
import (
"context"
"log"
"time"
"alox.tool/api"
"alox.tool/eventbus"
"alox.tool/uart"
)
type OTAManager struct {
Bus eventbus.EventBus
Com *uart.Com
Update [][]byte
CurrentSlice uint16
Partition byte
StartTime time.Time
EndTime time.Time
}
func NewOTAManager(bus eventbus.EventBus, com *uart.Com, update [][]byte) OTAManager {
return OTAManager{
Bus: bus,
Com: com,
Update: update,
CurrentSlice: 0,
}
}
func (om *OTAManager) StartUpdateHandler(ctx context.Context) {
RXC := om.Bus.Subscribe(api.TopicUARTRx)
defer om.Bus.Unsubscribe(api.TopicUARTRx, RXC)
go func() {
for {
select {
case <-ctx.Done():
return
case msg := <-RXC:
val, ok := msg.(api.Frame)
if !ok {
log.Printf("val is not type api.Frame its %T", val)
continue
}
log.Printf("[%d] Frame: %X, % X", val.Time, val.ID, val.Data)
om.processFrame(val)
}
}
}()
}
func (om *OTAManager) processFrame(val api.Frame) {
switch val.ID {
case api.CmdOtaStart:
msgT, err := uart.ParseFrameOtaStart(val)
if err != nil {
log.Printf("Could not Parse Client Input %v", err)
return
}
// Send First Payload
om.StartTime = time.Now()
om.Partition = msgT.Parition
err = om.Com.Send(api.CmdOtaPayload, om.Update[om.CurrentSlice])
if err != nil {
log.Printf("Error Sending Update Step!: %v", err)
return
}
om.CurrentSlice = om.CurrentSlice + 1
log.Printf("First Update Step %d", om.CurrentSlice)
log.Printf("%v", msgT)
case api.CmdOtaPayload:
msgT, err := uart.ParseFrameOtaPayload(val)
if err != nil {
log.Printf("Could not Parse Client Input %v", err)
return
}
// Send Next Payload until there is no more then send end package
log.Printf("msgT %v", msgT)
if msgT.Error != 0x00 {
log.Printf("Error in Sending Update! Check ESP Log")
return
}
log.Printf("NEXT PAYLOAD")
if om.CurrentSlice == uint16(len(om.Update)) {
log.Printf("LAST PAYLOAD SEND ENDING")
om.Com.Send(api.CmdOtaEnd, make([]byte, 1))
return
}
err = om.Com.Send(api.CmdOtaPayload, om.Update[om.CurrentSlice])
if err != nil {
log.Printf("Error Sending Update Step!: %v", err)
return
}
om.CurrentSlice = om.CurrentSlice + 1
log.Printf("UPDATE CURRENT SLICE %d/%d", om.CurrentSlice, len(om.Update))
log.Printf("UPDATE Part/WriteIndex %d/%d", msgT.SequenzCounter, msgT.WriteIndex)
log.Printf("Progress: %05.2f%%", (float32(om.CurrentSlice)/float32(len(om.Update)))*100)
case api.CmdOtaStatus:
v, err := uart.ParseFrameOtaStatus(val)
if err != nil {
log.Printf("Could not Parse Client Input %v", err)
return
}
log.Printf("%v", v)
// Update State Machine
case api.CmdOtaEnd:
msgT, err := uart.ParseFrameOtaEnd(val)
if err != nil {
log.Printf("Could not Parse Client Input %v", err)
return
}
// End bestätigung
om.EndTime = time.Now()
duration := om.EndTime.Sub(om.StartTime)
log.Printf("Partition %d Update done in %f.2s!", om.Partition, duration.Seconds())
log.Printf("%v", msgT)
case api.CmdOtaStartEspNow:
v, err := uart.ParseFrameOtaStartEspNow(val)
if err != nil {
log.Printf("Could not Parse Client Input %v", err)
return
}
//bus.Publish(api.TopicOTA, v)
log.Printf("%v", v)
}
}