Compare commits

..

No commits in common. "0bcacb4a53313d97f67163d24d1b42e111a194d4" and "d0ff63783f246dd2386043a00e8023947fed3dcb" have entirely different histories.

11 changed files with 36 additions and 389 deletions

View File

@ -5,8 +5,6 @@ const (
TopicUARTRx = "uart:rx" TopicUARTRx = "uart:rx"
TopicUARTTx = "uart:tx" TopicUARTTx = "uart:tx"
TopicUARTError = "uart:error" TopicUARTError = "uart:error"
TopicOTA = "ota"
) )
type Frame struct { type Frame struct {
@ -20,12 +18,6 @@ const (
CmdVersion byte = 0x02 CmdVersion byte = 0x02
CmdClientInfo byte = 0x03 CmdClientInfo byte = 0x03
CmdClientInput byte = 0x04 CmdClientInput byte = 0x04
CmdOtaStart byte = 0x10
CmdOtaPayload byte = 0x11
CmdOtaEnd byte = 0x12
CmdOtaStatus byte = 0x13
CmdOtaStartEspNow byte = 0x14
) )
const ( const (
@ -58,30 +50,3 @@ type PayloadClientInput struct {
Y float32 Y float32
InputMask uint32 InputMask uint32
} }
type PayloadOtaStatus struct {
SequenzCounter uint16
WriteIndex uint16
Data []byte
}
type PayloadOtaStart struct {
Data []byte
Parition byte
Error byte
}
type PayloadOtaEnd struct {
Data []byte
}
type PayloadOtaPayload struct {
SequenzCounter uint16
WriteIndex uint16
Data []byte
Error byte
}
type PayloadOtaStartEspNow struct {
Data []byte
}

View File

@ -1,11 +1,9 @@
package main package main
import ( import (
"context"
"flag" "flag"
"fmt" "fmt"
"log" "log"
"os"
"time" "time"
"alox.tool/api" "alox.tool/api"
@ -27,8 +25,7 @@ func main() {
Port: 8000, Port: 8000,
Host: "0.0.0.0", Host: "0.0.0.0",
UartPort: "/dev/ttyUSB0", UartPort: "/dev/ttyUSB0",
//Baudrate: 115200, Baudrate: 115200,
Baudrate: 921600,
} }
if Tests { if Tests {
StartTests(config) StartTests(config)
@ -64,55 +61,15 @@ func StartApp(config Config) {
} }
defer com.Close() defer com.Close()
update, err := os.ReadFile("../espAlox.bin") tr := testrunner.New(bus, com)
if err != nil { tr.RunVersionTest()
log.Printf("Could not read Update file %v", err)
return
}
updateSlices := SliceUpdate(update, 200)
oManager := NewOTAManager(bus, com, updateSlices)
ctx, cancle := context.WithCancel(context.Background())
defer cancle()
StartMessageHandling(ctx, bus)
oManager.StartUpdateHandler(ctx)
time.Sleep(time.Millisecond * 5)
//tr := testrunner.New(bus, com)
//tr.RunVersionTest()
time.Sleep(time.Millisecond * 5)
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.CmdOtaStart, 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() { go func() {
for { for {
select { select {
case <-ctx.Done(): case _ = <-bus.Subscribe(api.TopicUARTTx):
return
case _ = <-TXC:
//log.Printf("MSG[TX]: % X", msg) //log.Printf("MSG[TX]: % X", msg)
case msg := <-RXC: case msg := <-bus.Subscribe(api.TopicUARTRx):
//log.Printf("MSG[RX]: % X", msg) //log.Printf("MSG[RX]: % X", msg)
val, ok := msg.(api.Frame) val, ok := msg.(api.Frame)
if !ok { if !ok {
@ -123,7 +80,6 @@ func StartMessageHandling(ctx context.Context, bus eventbus.EventBus) {
switch val.ID { switch val.ID {
case api.CmdEcho: case api.CmdEcho:
log.Printf("Echo %v", val)
case api.CmdVersion: case api.CmdVersion:
v, err := uart.ParseFrameVersion(val) v, err := uart.ParseFrameVersion(val)
if err != nil { if err != nil {
@ -158,59 +114,19 @@ func StartMessageHandling(ctx context.Context, bus eventbus.EventBus) {
log.Printf("\tY %f", c.Y) log.Printf("\tY %f", c.Y)
log.Printf("\tBitmask %08b", c.InputMask) 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 { time.Sleep(time.Millisecond * 5)
updateSlices := [][]byte{}
for i := 0; i < len(update); i += 200 { com.Send(api.CmdEcho, make([]byte, 0))
end := min(i+200, len(update)) com.Send(api.CmdVersion, make([]byte, 0))
updateSlices = append(updateSlices, update[i:end]) com.Send(api.CmdClientInfo, make([]byte, 0))
} com.Send(api.CmdClientInput, make([]byte, 0))
return updateSlices
url := fmt.Sprintf("%s:%d", config.Host, config.Port)
fserver := frontend.New(bus)
fserver.Start(url)
} }

View File

@ -1,98 +0,0 @@
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) {
OtaChanel := om.Bus.Subscribe(api.TopicOTA)
go func() {
for {
select {
case <-ctx.Done():
return
case msg := <-OtaChanel:
om.handleOtaMessage(msg)
}
}
}()
}
func (om *OTAManager) handleOtaMessage(msg any) {
switch msgT := msg.(type) {
case api.PayloadOtaStart:
// 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.PayloadOtaPayload:
// 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.PayloadOtaEnd:
// 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)
}
}

View File

@ -87,7 +87,6 @@ func packFrame(id byte, payload []byte) []byte {
func (c *Com) Send(id byte, payload []byte) error { func (c *Com) Send(id byte, payload []byte) error {
raw := packFrame(id, payload) raw := packFrame(id, payload)
log.Printf("[RAW]: %v", raw)
//log.Printf("RAW: % X", raw) //log.Printf("RAW: % X", raw)
_, err := c.port.Write(raw) _, err := c.port.Write(raw)

View File

@ -115,75 +115,5 @@ func ParseFrameClientInput(frame api.Frame) ([]api.PayloadClientInput, error) {
} }
return clientList, nil return clientList, nil
}
// Dummy for now Just get Data
func ParseFrameOtaPayload(frame api.Frame) (api.PayloadOtaPayload, error) {
if len(frame.Data) == 0 {
return api.PayloadOtaPayload{}, fmt.Errorf("empty frame data")
}
status := api.PayloadOtaPayload{
Data: frame.Data,
SequenzCounter: binary.LittleEndian.Uint16(frame.Data[0:2]),
WriteIndex: binary.LittleEndian.Uint16(frame.Data[2:4]),
Error: frame.Data[4],
}
return status, nil
}
// Dummy for now Just get Data
func ParseFrameOtaStatus(frame api.Frame) (api.PayloadOtaStatus, error) {
if len(frame.Data) == 0 {
return api.PayloadOtaStatus{}, fmt.Errorf("empty frame data")
}
status := api.PayloadOtaStatus{
Data: frame.Data,
SequenzCounter: binary.LittleEndian.Uint16(frame.Data[0:2]),
WriteIndex: binary.LittleEndian.Uint16(frame.Data[2:4]),
}
return status, nil
}
// Dummy for now Just get Data
func ParseFrameOtaStart(frame api.Frame) (api.PayloadOtaStart, error) {
if len(frame.Data) == 0 {
return api.PayloadOtaStart{}, fmt.Errorf("empty frame data")
}
status := api.PayloadOtaStart{
Data: frame.Data,
Parition: frame.Data[0],
Error: frame.Data[1],
}
return status, nil
}
// Dummy for now Just get Data
func ParseFrameOtaEnd(frame api.Frame) (api.PayloadOtaEnd, error) {
if len(frame.Data) == 0 {
return api.PayloadOtaEnd{}, fmt.Errorf("empty frame data")
}
status := api.PayloadOtaEnd{
Data: frame.Data,
}
return status, nil
}
// Dummy for now Just get Data
func ParseFrameOtaStartEspNow(frame api.Frame) (api.PayloadOtaStartEspNow, error) {
if len(frame.Data) == 0 {
return api.PayloadOtaStartEspNow{}, fmt.Errorf("empty frame data")
}
status := api.PayloadOtaStartEspNow{
Data: frame.Data,
}
return status, nil
} }

View File

@ -373,9 +373,8 @@ void app_main(void) {
RegisterCallback(UART_CLIENT_INFO, clientInfoCallback); RegisterCallback(UART_CLIENT_INFO, clientInfoCallback);
RegisterCallback(UART_CLIENT_INPUT, fakeDataCallback); RegisterCallback(UART_CLIENT_INPUT, fakeDataCallback);
RegisterCallback(UART_OTA_START_ESPNOW, start_ota_update_espnow); RegisterCallback(UART_OTA_START_ESPNOW, start_ota_update_espnow);
RegisterUART_OTAFunctions();
// init_i2c_with_all_devices(); init_i2c_with_all_devices();
} else { } else {
ESP_LOGI(TAG, "Started in Slavemode"); ESP_LOGI(TAG, "Started in Slavemode");

View File

@ -13,7 +13,6 @@ void InitMessageBroker() {
} }
void RegisterCallback(uint8_t msgid, RegisterFunctionCallback callback) { void RegisterCallback(uint8_t msgid, RegisterFunctionCallback callback) {
ESP_LOGI(TAG, "Registerd Uart Callback for % X", msgid);
mr.FunctionList[mr.num_direct_callbacks].MSGID = msgid; mr.FunctionList[mr.num_direct_callbacks].MSGID = msgid;
mr.FunctionList[mr.num_direct_callbacks].callback = callback; mr.FunctionList[mr.num_direct_callbacks].callback = callback;
mr.num_direct_callbacks++; mr.num_direct_callbacks++;
@ -47,13 +46,11 @@ void MessageBrokerTask(void *param) {
while (1) { while (1) {
if (xQueueReceive(msg_queue, &received_msg, portMAX_DELAY)) { if (xQueueReceive(msg_queue, &received_msg, portMAX_DELAY)) {
// ESP_LOGI(TAG, "Received message from queue: MSGID=0x%02X, Length=%u", //ESP_LOGI(TAG, "Received message from queue: MSGID=0x%02X, Length=%u",
// received_msg.msgid, received_msg.payload_len); // received_msg.msgid, received_msg.payload_len);
for (int i = 0; i < mr.num_direct_callbacks; i++) { for (int i = 0; i < mr.num_direct_callbacks; i++) {
//ESP_LOGI(TAG, "Searching CALLBACK for %d", received_msg.msgid);
if (mr.FunctionList[i].MSGID == received_msg.msgid) { if (mr.FunctionList[i].MSGID == received_msg.msgid) {
//ESP_LOGI(TAG, "FOUND CALLBACK");
mr.FunctionList[i].callback( mr.FunctionList[i].callback(
received_msg.msgid, received_msg.data, received_msg.payload_len, received_msg.msgid, received_msg.data, received_msg.payload_len,
send_payload_buffer, send_payload_buffer_size, send_payload_buffer, send_payload_buffer_size,

View File

@ -353,16 +353,14 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload,
int part = prepare_ota_update(); int part = prepare_ota_update();
uart_ota_start_t *start = (uart_ota_start_t *)send_payload_buffer; // TODO: what does this do? maybe comment it out for now?
start->partition = part & 0xff;
// TODO: Refine Errors
// Set error
if (part < 0) { if (part < 0) {
start->error = 0x01; send_payload_buffer[1] = (part * -1) & 0xff;
} else {
send_payload_buffer[0] = part & 0xff;
} }
int send_payload_len = sizeof(uart_ota_start_t); int send_payload_len = 2;
int len = build_message(UART_OTA_START, send_payload_buffer, send_payload_len, int len = build_message(UART_OTA_START, send_payload_buffer, send_payload_len,
send_buffer, send_buffer_size); send_buffer, send_buffer_size);
if (len < 0) { if (len < 0) {
@ -377,9 +375,9 @@ void start_uart_update(uint8_t msgid, const uint8_t *payload,
} }
esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload) { esp_err_t write_ota_update(uint32_t write_len, const uint8_t *payload) {
// ESP_LOGI(TAG, "write_ota_update: write_len: %d", write_len); ESP_LOGI(TAG, "write_ota_update: write_len: %d", write_len);
// ESP_LOGI(TAG, "write_ota_update: update_buffer_write_index: %d", ESP_LOGI(TAG, "write_ota_update: update_buffer_write_index: %d",
// update_buffer_write_index); update_buffer_write_index);
if (update_buffer_write_index + write_len > UPDATE_BUFFER_SIZE) { if (update_buffer_write_index + write_len > UPDATE_BUFFER_SIZE) {
ESP_LOGI(TAG, "write_ota_update: schreib das update weg!"); ESP_LOGI(TAG, "write_ota_update: schreib das update weg!");
esp_err_t err = esp_err_t err =
@ -414,17 +412,15 @@ void payload_uart_update(uint8_t msgid, const uint8_t *payload_data_from_uart,
esp_err_t err = write_ota_update(write_len, actual_firmware_data); esp_err_t err = write_ota_update(write_len, actual_firmware_data);
uart_ota_ack_t *ack = (uart_ota_ack_t *)send_payload_buffer;
ack->sequence_counter = sequenz_counter;
ack->write_index = update_buffer_write_index;
ack->error = (err == ESP_OK) ? 0x00 : 0x01;
size_t send_payload_len = sizeof(uart_ota_ack_t);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err); ESP_LOGE(TAG, "GOT ESP ERROR WRITE OTA %d", err);
} }
size_t send_payload_len = 4;
memcpy(send_payload_buffer, &sequenz_counter, 2);
memcpy(&send_payload_buffer[2], &update_buffer_write_index, 2);
send_payload_buffer[4] = 0x00; // error
int len = build_message(UART_OTA_PAYLOAD, send_payload_buffer, int len = build_message(UART_OTA_PAYLOAD, send_payload_buffer,
send_payload_len, send_buffer, send_buffer_size); send_payload_len, send_buffer, send_buffer_size);
if (len < 0) { if (len < 0) {
@ -446,10 +442,8 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len,
esp_err_t err = end_ota_update(); esp_err_t err = end_ota_update();
uart_ota_end_t *end = (uart_ota_end_t *)send_payload_buffer; int send_payload_len = 1;
end->error = err & 0xff; send_payload_buffer[0] = err & 0xff;
int send_payload_len = sizeof(uart_ota_end_t);
int len = build_message(UART_OTA_END, send_payload_buffer, send_payload_len, int len = build_message(UART_OTA_END, send_payload_buffer, send_payload_len,
send_buffer, send_buffer_size); send_buffer, send_buffer_size);
if (len < 0) { if (len < 0) {
@ -467,9 +461,7 @@ void end_uart_update(uint8_t msgid, const uint8_t *payload, size_t payload_len,
void init_ota() { void init_ota() {
ota_task_queue = xQueueCreate(50, sizeof(ota_task_queue_message_t)); ota_task_queue = xQueueCreate(50, sizeof(ota_task_queue_message_t));
}
void RegisterUART_OTAFunctions() {
RegisterCallback(UART_OTA_START, start_uart_update); RegisterCallback(UART_OTA_START, start_uart_update);
RegisterCallback(UART_OTA_PAYLOAD, payload_uart_update); RegisterCallback(UART_OTA_PAYLOAD, payload_uart_update);
RegisterCallback(UART_OTA_END, end_uart_update); RegisterCallback(UART_OTA_END, end_uart_update);
@ -493,17 +485,7 @@ int prepare_ota_update() {
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err)); ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
return -2; return -2;
} }
if (update_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_0) {
return 0; return 0;
}
if (update_partition->subtype == ESP_PARTITION_SUBTYPE_APP_OTA_1) {
return 1;
}
// TODO: Unknow partition
return 2;
} }
esp_err_t end_ota_update() { esp_err_t end_ota_update() {

View File

@ -33,23 +33,7 @@ typedef struct {
ClientList *client_list; ClientList *client_list;
} MasterOTA_TaskParams_t; } MasterOTA_TaskParams_t;
typedef struct __attribute__((packed)) {
uint16_t sequence_counter;
uint16_t write_index;
uint8_t error;
} uart_ota_ack_t;
typedef struct __attribute__((packed)) {
uint8_t partition;
uint8_t error;
} uart_ota_start_t;
typedef struct __attribute__((packed)) {
uint8_t error;
} uart_ota_end_t;
void init_ota(); void init_ota();
void RegisterUART_OTAFunctions();
void MasterOTATask(void *pvParameter); void MasterOTATask(void *pvParameter);
void slave_ota_task(void *pvParameter); void slave_ota_task(void *pvParameter);

View File

@ -18,8 +18,7 @@ static const char *TAG = "ALOX - UART";
static QueueHandle_t parsed_message_queue; static QueueHandle_t parsed_message_queue;
void init_uart(QueueHandle_t msg_queue_handle) { void init_uart(QueueHandle_t msg_queue_handle) {
uart_config_t uart_config = {// .baud_rate = 115200, // 921600, 115200 uart_config_t uart_config = {.baud_rate = 921600, // 921600, 115200
.baud_rate = 921600,
.data_bits = UART_DATA_8_BITS, .data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE, .parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1, .stop_bits = UART_STOP_BITS_1,

View File

@ -1,29 +1,3 @@
# Convetions
## Naming
### Filenames: snake_case (ota_master.c, ota_slave.c, com_handler.c)
### Functions: module_submodule_action()
- OTA Master = ota_m_send_chunk(), ota_m_init()
- OTA Slave = ota_s_handle_chunk(), ota_s_prepare_flash()
- com_init(), msg_parse()
### Variables:
- Global: g_ (g_client_list)
- Statics: s_ (s_update_handle)
- Constants: UPPER_SNAKE_CASE (UPDATE_BUFFER_SIZE)
### Types:
- Typedefs: Ends with _t (ota_payload_t)
- Struct-Tags: Ends with _t or spezifik name (struct ota_context)
- Unions: Ends with _u (msg_payload_u)
- Callbacks: End with _cb (com_m_rx_cb)
### FreeRTOS-Objects
- x for Basetypes (x_ota_queue, x_status_semaphor)
- v for void return (v_ota_task)
# UART Protokoll # UART Protokoll
## Struktur einer Nachricht ## Struktur einer Nachricht