diff --git a/.github/workflows/publish-go-tester-task.yml b/.github/workflows/publish-go-tester-task.yml index 8e72c351..89d5c2b4 100644 --- a/.github/workflows/publish-go-tester-task.yml +++ b/.github/workflows/publish-go-tester-task.yml @@ -65,7 +65,7 @@ jobs: #use the strategy instead because we still use the native build strategy: matrix: - os: [ubuntu-20.04, windows-2019, macos-13] + os: [ubuntu-22.04, windows-2019, macos-13] arch: [-amd64] include: - os: windows-2019 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6275922c..12b3781b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: prerelease: ${{ steps.prerelease.outputs.IS_PRE }} strategy: matrix: - os: [ubuntu-20.04, windows-2019, macos-13] + os: [ubuntu-22.04, windows-2019, macos-13] arch: [amd64] include: - os: windows-2019 @@ -88,7 +88,7 @@ jobs: - name: Build the Agent for linux run: task go:build - if: matrix.os == 'ubuntu-20.04' + if: matrix.os == 'ubuntu-22.04' # the manifest is required by windows GUI apps, otherwise the binary will crash with: "Unable to create main window: TTM_ADDTOOL failed" (for reference https://github.com/lxn/walk/issues/28) # rsrc will produce a *.syso file that should get automatically recognized by go build command and linked into an executable. @@ -390,7 +390,7 @@ jobs: # This job is responsible for generating the installers (using installbuilder) package: needs: build - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: # vars used by installbuilder @@ -400,10 +400,10 @@ jobs: strategy: fail-fast: false # if one os is failing continue nonetheless matrix: # used to generate installers for different OS and not for runs-on - os: [ubuntu-20.04, windows-2019] + os: [ubuntu-22.04, windows-2019] arch: [amd64] include: - - os: ubuntu-20.04 + - os: ubuntu-22.04 platform-name: linux installbuilder-name: linux-x64 installer-extension: .run @@ -438,7 +438,7 @@ jobs: # zip artifacts do not mantain executable permission - name: Make executable run: chmod -v +x artifacts/${{ matrix.platform-name }}/${{ env.PROJECT_NAME }}* - if: matrix.os == 'ubuntu-20.04' + if: matrix.os == 'ubuntu-22.04' - name: Rename executable to Arduino_Cloud_Agent run: mv -v artifacts/${{ matrix.platform-name }}/${{ env.PROJECT_NAME }}${{ matrix.extension }} artifacts/${{ matrix.platform-name }}/Arduino_Cloud_Agent${{ matrix.extension }} @@ -451,7 +451,7 @@ jobs: - name: Generate archive run: tar -czvf ArduinoCloudAgent-${GITHUB_REF##*/}-${{ matrix.platform-name }}-${{ matrix.arch }}-installer.tar.gz ArduinoCloudAgent-${GITHUB_REF##*/}-${{ matrix.platform-name }}-${{ matrix.arch }}-installer${{matrix.installer-extension}} - if: matrix.os == 'ubuntu-20.04' + if: matrix.os == 'ubuntu-22.04' - name: Upload artifacts uses: actions/upload-artifact@v4 @@ -606,7 +606,7 @@ jobs: if-no-files-found: error create-release: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 environment: production needs: [build, generate-sign-dmg, sign-windows] diff --git a/Taskfile.yml b/Taskfile.yml index bba07548..681c8274 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -149,6 +149,20 @@ tasks: - task: go:vet - task: go:lint + autoupdate:demo: + desc: Demo the local auto-update workflow for the Agent (for linux and mac user) + prompt: Before continuing, please make sure you’ve opened the "Open Configuration" option from the Agent menu and set the updateUrl=http://127.0.0.1:3000/ + cmds: + - task: go:build + - go install github.com/sanbornm/go-selfupdate/...@latest + # NOTE: the path 'CreateAgent/Stable' is important to keep as is + # because agent searches the update files into "CreateAgent/Stable/{platform}.json" and "https://downloads.arduino.cc/CreateAgent/Stable/{version}/{platform}.gz" + - go-selfupdate -o public/CreateAgent/Stable ./arduino-cloud-agent {{.VERSION}} + - docker rm -f agent-static-server + - docker run --rm -d -v "$PWD/public:/usr/share/nginx/html:ro" -p 3000:80 --name agent-static-server nginx:alpine + - sleep 5 # wait the server is up before starting the update + - curl -X POST http://127.0.0.1:8991/update + vars: # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/release-go-task/Taskfile.yml PROJECT_NAME: arduino-cloud-agent diff --git a/serial.go b/serial.go index 64e5b8f7..1a43f364 100755 --- a/serial.go +++ b/serial.go @@ -31,7 +31,7 @@ import ( type serialhub struct { // Opened serial ports. - ports map[*serport]bool + ports map[string]*serport mu sync.Mutex } @@ -60,7 +60,7 @@ type SpPortItem struct { var serialPorts SerialPortList var sh = serialhub{ - ports: make(map[*serport]bool), + ports: make(map[string]*serport), } // Register serial ports from the connections. @@ -68,7 +68,7 @@ func (sh *serialhub) Register(port *serport) { sh.mu.Lock() //log.Print("Registering a port: ", p.portConf.Name) h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Got register/open on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + ",\"BufferType\":\"" + port.BufferType + "\"}") - sh.ports[port] = true + sh.ports[port.portName] = port sh.mu.Unlock() } @@ -77,7 +77,7 @@ func (sh *serialhub) Unregister(port *serport) { sh.mu.Lock() //log.Print("Unregistering a port: ", p.portConf.Name) h.broadcastSys <- []byte("{\"Cmd\":\"Close\",\"Desc\":\"Got unregister/close on port.\",\"Port\":\"" + port.portConf.Name + "\",\"Baud\":" + strconv.Itoa(port.portConf.Baud) + "}") - delete(sh.ports, port) + delete(sh.ports, port.portName) close(port.sendBuffered) close(port.sendNoBuf) sh.mu.Unlock() @@ -86,15 +86,8 @@ func (sh *serialhub) Unregister(port *serport) { func (sh *serialhub) FindPortByName(portname string) (*serport, bool) { sh.mu.Lock() defer sh.mu.Unlock() - - for port := range sh.ports { - if strings.EqualFold(port.portConf.Name, portname) { - // we found our port - //spHandlerClose(port) - return port, true - } - } - return nil, false + port, ok := sh.ports[portname] + return port, ok } // List broadcasts a Json representation of the ports found diff --git a/serialport.go b/serialport.go index 0d386bbf..b3418fe5 100755 --- a/serialport.go +++ b/serialport.go @@ -20,6 +20,7 @@ import ( "encoding/base64" "io" "strconv" + "sync" "sync/atomic" "time" "unicode/utf8" @@ -273,7 +274,13 @@ func (p *serport) writerRaw() { h.broadcastSys <- []byte(msgstr) } +// This lock is used to prevent multiple threads from trying to open the same port at the same time. +// It presents issues with the serial port driver on some OS's: https://github.com/arduino/arduino-create-agent/issues/1031 +var spHandlerOpenLock sync.Mutex + func spHandlerOpen(portname string, baud int, buftype string) { + spHandlerOpenLock.Lock() + defer spHandlerOpenLock.Unlock() log.Print("Inside spHandler") @@ -295,11 +302,14 @@ func spHandlerOpen(portname string, baud int, buftype string) { sp, err := serial.Open(portname, mode) log.Print("Just tried to open port") if err != nil { - //log.Fatal(err) - log.Print("Error opening port " + err.Error()) - //h.broadcastSys <- []byte("Error opening port. " + err.Error()) - h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}") - + existingPort, ok := sh.FindPortByName(portname) + if ok && existingPort.portConf.Baud == baud && existingPort.BufferType == buftype { + log.Print("Port already opened") + h.broadcastSys <- []byte("{\"Cmd\":\"Open\",\"Desc\":\"Port already opened.\",\"Port\":\"" + existingPort.portConf.Name + "\",\"Baud\":" + strconv.Itoa(existingPort.portConf.Baud) + ",\"BufferType\":\"" + existingPort.BufferType + "\"}") + } else { + log.Print("Error opening port " + err.Error()) + h.broadcastSys <- []byte("{\"Cmd\":\"OpenFail\",\"Desc\":\"Error opening port. " + err.Error() + "\",\"Port\":\"" + conf.Name + "\",\"Baud\":" + strconv.Itoa(conf.Baud) + "}") + } return } log.Print("Opened port successfully") @@ -331,7 +341,6 @@ func spHandlerOpen(portname string, baud int, buftype string) { p.bufferwatcher = bw sh.Register(p) - defer sh.Unregister(p) serialPorts.MarkPortAsOpened(portname) serialPorts.List() @@ -342,10 +351,12 @@ func spHandlerOpen(portname string, baud int, buftype string) { go p.writerNoBuf() // this is thread to send to serial port but with base64 decoding go p.writerRaw() - - p.reader(buftype) - - serialPorts.List() + // this is the thread that reads from the serial port + go func() { + p.reader(buftype) + serialPorts.List() + sh.Unregister(p) + }() } func (p *serport) Close() {
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: