Improved GoTool
This commit is contained in:
parent
4628041b55
commit
9b2474c261
141
goTool/main.go
141
goTool/main.go
@ -11,24 +11,29 @@ import (
|
||||
"alox.tool/api"
|
||||
"alox.tool/eventbus"
|
||||
"alox.tool/frontend"
|
||||
"alox.tool/state"
|
||||
"alox.tool/testrunner"
|
||||
"alox.tool/uart"
|
||||
)
|
||||
|
||||
var (
|
||||
Tests bool
|
||||
Baudrate uint
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.BoolVar(&Tests, "t", false, "Tests")
|
||||
flag.UintVar(&Baudrate, "b", 921600, "Baudrate") // 115200
|
||||
|
||||
flag.Parse()
|
||||
|
||||
log.Printf("Starting with Params %v", Baudrate)
|
||||
|
||||
config := Config{
|
||||
Port: 8000,
|
||||
Host: "0.0.0.0",
|
||||
UartPort: "/dev/ttyUSB0",
|
||||
//Baudrate: 115200,
|
||||
Baudrate: 921600,
|
||||
Baudrate: int(Baudrate),
|
||||
}
|
||||
if Tests {
|
||||
StartTests(config)
|
||||
@ -51,13 +56,14 @@ func StartTests(config Config) {
|
||||
|
||||
tr := testrunner.New(bus, com)
|
||||
|
||||
testTest1 := make(map[string]func() error)
|
||||
testTest1["Echo Test"] = tr.RunEchoTest
|
||||
testTest1["Version Test"] = tr.RunVersionTest
|
||||
testTest1["Info Test"] = tr.RunClientInfoTest
|
||||
testTest1["Input Test"] = tr.RunClientInputTest
|
||||
testTest := make(map[string]func() error)
|
||||
testTest["Echo Test"] = tr.RunEchoTest
|
||||
testTest["Version Test"] = tr.RunVersionTest
|
||||
testTest["Info Test"] = tr.RunClientInfoTest
|
||||
testTest["Input Test"] = tr.RunClientInputTest
|
||||
testTest["Rebuild Network"] = tr.RebuildNetwork
|
||||
|
||||
tr.RunTestSet(testTest1)
|
||||
tr.RunTestSet(testTest)
|
||||
}
|
||||
|
||||
func StartApp(config Config) {
|
||||
@ -88,7 +94,8 @@ func StartApp(config Config) {
|
||||
|
||||
oManager := NewOTAManager(bus, com, updateSlices)
|
||||
|
||||
StartMessageHandling(ctx, bus)
|
||||
espHandle := state.New()
|
||||
espHandle.Start(ctx, bus)
|
||||
oManager.StartUpdateHandler(ctx)
|
||||
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
@ -98,127 +105,19 @@ func StartApp(config Config) {
|
||||
|
||||
time.Sleep(time.Millisecond * 5)
|
||||
|
||||
com.Send(api.CmdEcho, make([]byte, 0))
|
||||
com.Send(api.CmdVersion, make([]byte, 0))
|
||||
//com.Send(api.CmdEcho, make([]byte, 0))
|
||||
//com.Send(api.CmdVersion, make([]byte, 0))
|
||||
com.Send(api.CmdClientInfo, make([]byte, 0))
|
||||
com.Send(api.CmdClientInput, make([]byte, 0))
|
||||
//com.Send(api.CmdClientInput, make([]byte, 0))
|
||||
|
||||
//com.Send(api.CmdOtaStart, make([]byte, 0))
|
||||
com.Send(api.CmdOtaStartEspNow, make([]byte, 0))
|
||||
//com.Send(api.CmdOtaStartEspNow, make([]byte, 0))
|
||||
|
||||
url := fmt.Sprintf("%s:%d", config.Host, config.Port)
|
||||
fserver := frontend.New(bus)
|
||||
fserver.Start(url)
|
||||
}
|
||||
|
||||
func StartMessageHandling(ctx context.Context, bus eventbus.EventBus) {
|
||||
|
||||
RXC := bus.Subscribe(api.TopicUARTRx)
|
||||
defer bus.Unsubscribe(api.TopicUARTRx, RXC)
|
||||
TXC := bus.Subscribe(api.TopicUARTTx)
|
||||
defer bus.Unsubscribe(api.TopicUARTTx, TXC)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case _ = <-TXC:
|
||||
//log.Printf("MSG[TX]: % X", msg)
|
||||
case msg := <-RXC:
|
||||
//log.Printf("MSG[RX]: % X", msg)
|
||||
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)
|
||||
|
||||
switch val.ID {
|
||||
case api.CmdEcho:
|
||||
log.Printf("Echo %v", val)
|
||||
case api.CmdVersion:
|
||||
v, err := uart.ParseFrameVersion(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Version %v", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Version Info %d %s", v.Version, v.Buildhash)
|
||||
case api.CmdClientInfo:
|
||||
v, err := uart.ParseFrameClientInfo(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Info %v", err)
|
||||
continue
|
||||
}
|
||||
for _, c := range v {
|
||||
log.Printf("Client ID %d", c.ClientID)
|
||||
log.Printf("\tIsAvailable %d", c.IsAvailable)
|
||||
log.Printf("\tLastPing %d", c.LastPing)
|
||||
log.Printf("\tLastSuccessfulPing %d", c.LastSuccessfulPing)
|
||||
log.Printf("\tSlotIsUsed %d", c.SlotIsUsed)
|
||||
log.Printf("\tVersion %d", c.Version)
|
||||
log.Printf("\tMACAddr % X", c.MACAddr)
|
||||
}
|
||||
case api.CmdClientInput:
|
||||
v, err := uart.ParseFrameClientInput(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
for _, c := range v {
|
||||
log.Printf("Client ID %d", c.ClientID)
|
||||
log.Printf("\tX %f", c.X)
|
||||
log.Printf("\tY %f", c.Y)
|
||||
log.Printf("\tBitmask %08b", c.InputMask)
|
||||
}
|
||||
case api.CmdOtaPayload:
|
||||
v, err := uart.ParseFrameOtaPayload(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
bus.Publish(api.TopicOTA, v)
|
||||
log.Printf("%v", v)
|
||||
case api.CmdOtaStatus:
|
||||
v, err := uart.ParseFrameOtaStatus(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
bus.Publish(api.TopicOTA, v)
|
||||
log.Printf("%v", v)
|
||||
// Update State Machine
|
||||
|
||||
case api.CmdOtaStart:
|
||||
v, err := uart.ParseFrameOtaStart(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
bus.Publish(api.TopicOTA, v)
|
||||
log.Printf("%v", v)
|
||||
case api.CmdOtaEnd:
|
||||
v, err := uart.ParseFrameOtaEnd(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
bus.Publish(api.TopicOTA, v)
|
||||
log.Printf("%v", v)
|
||||
case api.CmdOtaStartEspNow:
|
||||
v, err := uart.ParseFrameOtaStartEspNow(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
continue
|
||||
}
|
||||
bus.Publish(api.TopicOTA, v)
|
||||
log.Printf("%v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func SliceUpdate(update []byte, maxlen int) [][]byte {
|
||||
updateSlices := [][]byte{}
|
||||
for i := 0; i < len(update); i += 200 {
|
||||
|
||||
@ -30,27 +30,40 @@ func NewOTAManager(bus eventbus.EventBus, com *uart.Com, update [][]byte) OTAMan
|
||||
}
|
||||
|
||||
func (om *OTAManager) StartUpdateHandler(ctx context.Context) {
|
||||
OtaChanel := om.Bus.Subscribe(api.TopicOTA)
|
||||
RXC := om.Bus.Subscribe(api.TopicUARTRx)
|
||||
defer om.Bus.Unsubscribe(api.TopicUARTRx, RXC)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case msg := <-OtaChanel:
|
||||
om.handleOtaMessage(msg)
|
||||
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) handleOtaMessage(msg any) {
|
||||
switch msgT := msg.(type) {
|
||||
case api.PayloadOtaStart:
|
||||
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])
|
||||
err = om.Com.Send(api.CmdOtaPayload, om.Update[om.CurrentSlice])
|
||||
if err != nil {
|
||||
log.Printf("Error Sending Update Step!: %v", err)
|
||||
return
|
||||
@ -58,7 +71,12 @@ func (om *OTAManager) handleOtaMessage(msg any) {
|
||||
om.CurrentSlice = om.CurrentSlice + 1
|
||||
log.Printf("First Update Step %d", om.CurrentSlice)
|
||||
log.Printf("%v", msgT)
|
||||
case api.PayloadOtaPayload:
|
||||
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)
|
||||
@ -74,7 +92,7 @@ func (om *OTAManager) handleOtaMessage(msg any) {
|
||||
om.Com.Send(api.CmdOtaEnd, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
err := om.Com.Send(api.CmdOtaPayload, om.Update[om.CurrentSlice])
|
||||
err = om.Com.Send(api.CmdOtaPayload, om.Update[om.CurrentSlice])
|
||||
if err != nil {
|
||||
log.Printf("Error Sending Update Step!: %v", err)
|
||||
return
|
||||
@ -84,15 +102,35 @@ func (om *OTAManager) handleOtaMessage(msg any) {
|
||||
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.PayloadOtaEnd:
|
||||
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.PayloadOtaStatus:
|
||||
log.Printf("%v", msgT)
|
||||
case api.PayloadOtaStartEspNow:
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
186
goTool/state/state.go
Normal file
186
goTool/state/state.go
Normal file
@ -0,0 +1,186 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"alox.tool/api"
|
||||
"alox.tool/eventbus"
|
||||
"alox.tool/uart"
|
||||
)
|
||||
|
||||
type ESPStateHandler struct {
|
||||
RWMutex sync.RWMutex
|
||||
Master MasterESP
|
||||
}
|
||||
|
||||
type ESPVersion struct {
|
||||
Version uint16
|
||||
Buildhash [7]byte
|
||||
}
|
||||
|
||||
type BaseESP struct {
|
||||
ClientId byte
|
||||
IsUpdating bool
|
||||
UpdateProgress float32
|
||||
Version ESPVersion
|
||||
RunningPartition int
|
||||
MAC [6]byte
|
||||
}
|
||||
|
||||
type MasterESP struct {
|
||||
BaseESP
|
||||
Slaves map[byte]*SlaveESP
|
||||
}
|
||||
|
||||
type SlaveESP struct {
|
||||
BaseESP
|
||||
SlotAvailable bool
|
||||
SlotUsed bool
|
||||
Bitmask uint32
|
||||
LageX float32
|
||||
LageY float32
|
||||
LastPing uint32
|
||||
LastSuccessfullPing uint32
|
||||
}
|
||||
|
||||
func New() *ESPStateHandler {
|
||||
return &ESPStateHandler{
|
||||
RWMutex: sync.RWMutex{},
|
||||
Master: NewMasterESP(),
|
||||
}
|
||||
}
|
||||
|
||||
func NewMasterESP() MasterESP {
|
||||
return MasterESP{
|
||||
BaseESP: BaseESP{
|
||||
ClientId: 0,
|
||||
IsUpdating: false,
|
||||
UpdateProgress: 0,
|
||||
Version: ESPVersion{
|
||||
Version: 0,
|
||||
Buildhash: [7]byte{},
|
||||
},
|
||||
RunningPartition: 0,
|
||||
MAC: [6]byte{},
|
||||
},
|
||||
Slaves: map[byte]*SlaveESP{},
|
||||
}
|
||||
}
|
||||
|
||||
func NewSlaveESP() *SlaveESP {
|
||||
return &SlaveESP{
|
||||
BaseESP: BaseESP{
|
||||
ClientId: 0,
|
||||
IsUpdating: false,
|
||||
UpdateProgress: 0,
|
||||
Version: ESPVersion{
|
||||
Version: 0,
|
||||
Buildhash: [7]byte{},
|
||||
},
|
||||
RunningPartition: 0,
|
||||
MAC: [6]byte{},
|
||||
},
|
||||
SlotAvailable: false,
|
||||
SlotUsed: false,
|
||||
Bitmask: 0,
|
||||
LageX: 0,
|
||||
LageY: 0,
|
||||
LastPing: 0,
|
||||
LastSuccessfullPing: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ESPStateHandler) Start(ctx context.Context, bus eventbus.EventBus) {
|
||||
go func() {
|
||||
RXC := bus.Subscribe(api.TopicUARTRx)
|
||||
defer bus.Unsubscribe(api.TopicUARTRx, RXC)
|
||||
|
||||
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)
|
||||
s.processFrame(val)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *ESPStateHandler) processFrame(val api.Frame) {
|
||||
s.RWMutex.Lock()
|
||||
defer s.RWMutex.Unlock()
|
||||
|
||||
switch val.ID {
|
||||
case api.CmdEcho:
|
||||
log.Printf("Echo %v", val)
|
||||
case api.CmdVersion:
|
||||
v, err := uart.ParseFrameVersion(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Version %v", err)
|
||||
return
|
||||
}
|
||||
log.Printf("Version Info %d %s", v.Version, v.Buildhash)
|
||||
|
||||
// Update State
|
||||
s.Master.Version.Version = v.Version
|
||||
s.Master.Version.Buildhash = v.Buildhash
|
||||
|
||||
case api.CmdClientInfo:
|
||||
v, err := uart.ParseFrameClientInfo(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Info %v", err)
|
||||
return
|
||||
}
|
||||
for _, c := range v {
|
||||
log.Printf("Client ID %d", c.ClientID)
|
||||
log.Printf("\tIsAvailable %d", c.IsAvailable)
|
||||
log.Printf("\tLastPing %d", c.LastPing)
|
||||
log.Printf("\tLastSuccessfulPing %d", c.LastSuccessfulPing)
|
||||
log.Printf("\tSlotIsUsed %d", c.SlotIsUsed)
|
||||
log.Printf("\tVersion %d", c.Version)
|
||||
log.Printf("\tMACAddr % X", c.MACAddr)
|
||||
|
||||
_, ok := s.Master.Slaves[c.ClientID]
|
||||
if !ok {
|
||||
s.Master.Slaves[c.ClientID] = NewSlaveESP()
|
||||
}
|
||||
|
||||
s.Master.Slaves[c.ClientID].SlotAvailable = c.IsAvailable != 0
|
||||
s.Master.Slaves[c.ClientID].SlotUsed = c.SlotIsUsed != 0
|
||||
s.Master.Slaves[c.ClientID].LastPing = c.LastPing
|
||||
s.Master.Slaves[c.ClientID].LastSuccessfullPing = c.LastSuccessfulPing
|
||||
s.Master.Slaves[c.ClientID].Version.Version = c.Version
|
||||
s.Master.Slaves[c.ClientID].MAC = c.MACAddr
|
||||
}
|
||||
|
||||
case api.CmdClientInput:
|
||||
v, err := uart.ParseFrameClientInput(val)
|
||||
if err != nil {
|
||||
log.Printf("Could not Parse Client Input %v", err)
|
||||
return
|
||||
}
|
||||
for _, c := range v {
|
||||
log.Printf("Client ID %d", c.ClientID)
|
||||
log.Printf("\tX %f", c.X)
|
||||
log.Printf("\tY %f", c.Y)
|
||||
log.Printf("\tBitmask %08b", c.InputMask)
|
||||
|
||||
_, ok := s.Master.Slaves[c.ClientID]
|
||||
if !ok {
|
||||
s.Master.Slaves[c.ClientID] = NewSlaveESP()
|
||||
}
|
||||
|
||||
s.Master.Slaves[c.ClientID].LageX = c.X
|
||||
s.Master.Slaves[c.ClientID].LageY = c.Y
|
||||
s.Master.Slaves[c.ClientID].Bitmask = c.InputMask
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user