Firmware checks, nearly ready to push firmware to device
This commit is contained in:
155
update/update.go
Normal file
155
update/update.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package update
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/albenik/go-serial/v2"
|
||||
"github.com/go-playground/log/v7"
|
||||
"github.com/schollz/progressbar/v3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const CHUNKSIZE = 256
|
||||
|
||||
type modem struct {
|
||||
port serial.Port
|
||||
}
|
||||
|
||||
func initmodem(serport string, baudrate int) (*modem, error) {
|
||||
p, err := serial.Open(serport,
|
||||
serial.WithBaudrate(baudrate),
|
||||
serial.WithDataBits(8),
|
||||
serial.WithParity(serial.NoParity),
|
||||
serial.WithStopBits(serial.OneStopBit),
|
||||
serial.WithReadTimeout(1000),
|
||||
serial.WithWriteTimeout(1000))
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: File %s could not be opened\n", serport)
|
||||
return nil, err
|
||||
}
|
||||
m := &modem{*p}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *modem) write(out string, nolog ...bool) ([]byte, error) {
|
||||
if len(nolog) == 0 {
|
||||
log.Debug("Sending " + out)
|
||||
} else {
|
||||
log.Debugf("Sending %d byte(s)", len(out))
|
||||
}
|
||||
m.port.Write([]byte(out))
|
||||
buff := make([]byte, 1024)
|
||||
time.Sleep(100 * time.Millisecond) // give the PTC some time to answer
|
||||
n, err := m.port.Read(buff)
|
||||
// fmt.Printf("Read %d bytes\n", n)
|
||||
if err != nil {
|
||||
log.Errorf("ERROR: cannot read answer from command: %s\n", out)
|
||||
return []byte(""), err
|
||||
}
|
||||
// TODO: Handle EOF
|
||||
return buff[:n], nil
|
||||
|
||||
}
|
||||
|
||||
func (m *modem) getSerNum() (string, error) {
|
||||
answer, err := m.write("\rsys sern\r")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
re := regexp.MustCompile(`Serial number: \w{2,16}`)
|
||||
sn := strings.ReplaceAll(string(re.Find(answer)), "Serial number: ", "")
|
||||
log.Infof("Serial Number is: %s", sn)
|
||||
return sn, nil
|
||||
}
|
||||
|
||||
func (m *modem) setDateTime() error {
|
||||
ct := time.Now()
|
||||
answer, err := m.write("DATE " + ct.Format("020106\r"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.Contains(string(answer), "BAD ARGUMENT") {
|
||||
return errors.New("setting DATE returns a BAD ARGUMENT error!")
|
||||
}
|
||||
answer, err = m.write("TIME " + ct.Format("150405\r"))
|
||||
if strings.Contains(string(answer), "BAD ARGUMENT") {
|
||||
return errors.New("setting TIME returns a BAD ARGUMENT error!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *modem) writeUpdate(fwfile string) error {
|
||||
_, err := m.write("UPDATE\r")
|
||||
if err != nil {
|
||||
_, _ = m.write("\033", true) // send ESC to cancel the update
|
||||
return err
|
||||
}
|
||||
answer, err := m.write("\006", true)
|
||||
if err != nil {
|
||||
_, _ = m.write("\033", true) // send ESC to cancel the update
|
||||
return err
|
||||
}
|
||||
// TODO: remove that once write process is established
|
||||
_, err = m.write("\033", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("flash stamp: % X", binary.LittleEndian.Uint32(answer[2:6]))
|
||||
flashId := binary.LittleEndian.Uint16(answer[0:2])
|
||||
log.Infof("flash id: % X", flashId)
|
||||
if flashId != 0xa41f && flashId != 0x5b1f && flashId != 0xda1f {
|
||||
_, _ = m.write("\033", true) // send ESC to cancel the update
|
||||
return errors.New("wrong flash id")
|
||||
}
|
||||
r, err := os.Open(fwfile)
|
||||
if err != nil {
|
||||
_, _ = m.write("\033", true) // send ESC to cancel the update
|
||||
return err
|
||||
}
|
||||
fstat, _ := r.Stat()
|
||||
fsize := fstat.Size()
|
||||
r.Close()
|
||||
|
||||
_, err = ioutil.ReadFile(fwfile)
|
||||
if err != nil {
|
||||
_, _ = m.write("\033", true) // send ESC to cancel the update
|
||||
return err
|
||||
}
|
||||
// fmt.Println(fsize)
|
||||
chunks := uint16(fsize / 256)
|
||||
if fsize%256 != 0 {
|
||||
chunks++
|
||||
}
|
||||
|
||||
// a := make([]byte, 2)
|
||||
// binary.BigEndian.PutUint16(a, chunks)
|
||||
|
||||
bar := progressbar.Default(int64(chunks), "flashing chunk")
|
||||
for i := 0; i < int(chunks); i++ {
|
||||
bar.Add(1)
|
||||
time.Sleep(3 * time.Millisecond)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Update(serport string, baudrate int, fwfile string) error {
|
||||
m, err := initmodem(serport, baudrate)
|
||||
defer m.port.Close()
|
||||
if err != nil {
|
||||
return errors.New("FEHLER in Update")
|
||||
}
|
||||
_, _ = m.getSerNum()
|
||||
if m.setDateTime() != nil {
|
||||
return err
|
||||
}
|
||||
if m.writeUpdate(fwfile) != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user