diff --git a/ArduinoCreateAgent.xml b/ArduinoCreateAgent.xml new file mode 100644 index 000000000..93b7783c7 --- /dev/null +++ b/ArduinoCreateAgent.xml @@ -0,0 +1,310 @@ + + ArduinoCreateAgent + arduino-create-agent + 1.0 + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/LICENSE.md + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/installer_icons/Installer.png + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/installer_icons/InstallerIcon.png + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/installer_icons/InstallerSplash.png + auto + + + default + Default Component + 1 + 1 + 1 + + + + ${installdir}/Arduino_Create_Bridge + ${installdir}/InstallerIcon.png + Arduino Create Agent + + linux-x64 + 0 + 0 + + + + + + + + + Program Files + ${installdir} + programfiles + all + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/fakecerts/cert.pem + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/fakecerts/key.pem + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/config.ini + + + + + Uninstall + ${installdir}/${uninstallerName} + + Uninstall ${product_fullname} + ${installdir} + all + 0 + 0 + ${installdir}/${uninstallerName}.exe + + + ${installdir} + + + + + Program Files + ${installdir} + programfileslinux + linux-x64 + + + 1 + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/linux_amd64/Arduino_Create_Bridge + + + /tmp/linux/arduino/arduino + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/installer_icons/InstallerIcon.png + + + + + Program Files + ${installdir} + programfileswindows + windows + + + 1 + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/windows_386/Arduino_Create_Bridge.exe + + + /tmp/windows/arduino/arduino + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/installer_icons/tray_iconWin.ico + + + + + Program Files + ${installdir} + programfilesosx + osx + + + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/darwin_amd64/Arduino_Create_Bridge + + + /tmp/macosx/arduino/arduino + + + + + Autostart + /etc/xdg/autostart + xdgautostart + linux-x64 + + + + ${installdir}/Arduino_Create_Bridge & + ${installdir}/InstallerIcon.png + arduino-create-agent + + linux-x64 + 0 + 0 + + + + + + + + + Autostart + ${windows_folder_common_startup} + winautostart + windows + + + + + + Arduino Create Agent + + windows + 0 + 0 + ${installdir}/Arduino_Create_Bridge.exe + + + + + + + + + + Uninstall ${product_fullname} + Uninstall ${product_fullname} + 0 + 0 + ${installdir}/${uninstallerName}.exe + + + ${installdir}/ + + + + Arduino Create Agent + 0 + 0 + ${installdir}/Arduino_Create_Bridge + + ${installdir}/tray_IconWin.ico + + + + + + + + /tmp/linux/arduino + + + /tmp/macosx/arduino + + + /tmp/windows/arduino + + + /tmp/linux/Arduino_Create_Bridge + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/linux_amd64/Arduino_Create_Bridge + + + /tmp/macosx/Arduino_Create_Bridge + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/darwin_amd64/Arduino_Create_Bridge + + + /tmp/windows/Arduino_Create_Bridge.exe + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/windows_386/Arduino_Create_Bridge.exe + + + /tmp/linux/arduino/ + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/linux_amd64/arduino.zip + + + /tmp/macosx/arduino/ + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/darwin_amd64/arduino.zip + + + /tmp/windows/arduino/ + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/snapshot/windows_386/arduino.zip + + + + + + 0 + ${installdir}/Arduino_Create_Bridge + + ${product_shortname} + + + + ${installdir}/Arduino_Create_Bridge + & + + + 1 + windows + + + + + schtasks + /create /sc onlogon /tn ArduinoCreateAgent /rl highest /tr "${installdir}/Arduino_Create_Bridge.exe" + Creating startup task + + + windows-2000 + + + + + ${installdir}/Arduino_Create_Bridge.exe + & + Launching Agent + 0 + ${installdir} + + + windows + + + + + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run + ArduinoCreateAgent + REG_SZ + "${installdir}/Arduino_Create_Bridge.exe" + + + windows + + + + + + + ${product_shortname} + + + schtasks + /delete /tn ArduinoCreateAgent /f + + + windows-2000 + + + + + 1 + 1 + 1 + 1 + Arduino LLC + /home/jenkins/jenkins/jobs/Create_Bridge_test/workspace/src/github.com/facchinm/systray/example/icon/iconwin.ico + + + installdir + Installer.Parameter.installdir.description + Installer.Parameter.installdir.explanation + + ${platform_install_prefix}/${product_shortname}-${product_version} + 0 + yes + prefix + yes + 0 + 30 + + + + diff --git a/README.md b/README.md index 8ab03a34f..9c41f8a30 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ serial-port-json-server ======================= -Get the latest version of the Bridge for all supported platforms: http://downloads.arduino.cc/CreateBridge/CreateBridge.zip +Get the latest version of the Bridge for all supported platforms: + +[Linux x64](http://downloads.arduino.cc/CreateBridge/ArduinoCreateAgent-1.0-linux-x64-installer.run) + +[MacOSX](http://downloads.arduino.cc/CreateBridge/ArduinoCreateAgent-1.0-osx-installer.dmg) + +[Windows](http://downloads.arduino.cc/CreateBridge/ArduinoCreateAgent-1.0-windows-installer.exe) Version 1.82 diff --git a/compile_webidebridge.sh b/compile_webidebridge.sh index a8dfd4398..e0349461e 100755 --- a/compile_webidebridge.sh +++ b/compile_webidebridge.sh @@ -34,10 +34,11 @@ createZipEmbeddableFileArduino() cd arduino zip -r arduino.zip arduino/* config.ini *.pem > /dev/null cd .. - cat arduino/arduino.zip >> $3 - zip --adjust-sfx $3 + #cat arduino/arduino.zip >> $3 + #zip --adjust-sfx $3 mkdir -p snapshot/$GOOS\_$GOARCH cp $3 snapshot/$GOOS\_$GOARCH/$3 + cp arduino/arduino.zip snapshot/$GOOS\_$GOARCH ls -la snapshot/$GOOS\_$GOARCH/$3 } @@ -53,7 +54,6 @@ bootstrapPlatforms() env CC_FOR_TARGET=i686-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=386 ./make.bash --no-clean } -set -x compilePlatform() { echo 'In compilePlatform' @@ -65,8 +65,9 @@ compilePlatform() if [ $GOOS == "windows" ] then NAME=$NAME".exe" + EXTRAFLAGS="-ldflags -H=windowsgui" fi - env GOOS=$GOOS GOARCH=$GOARCH CC=$CC CXX=$CC CGO_ENABLED=$CGO_ENABLED go build -o=$NAME + env GOOS=$GOOS GOARCH=$GOARCH CC=$CC CXX=$CC CGO_ENABLED=$CGO_ENABLED go build -o=$NAME $EXTRAFLAGS if [ $? != 0 ] then echo -e "${red}Target $GOOS, $GOARCH failed${NC}" @@ -74,7 +75,7 @@ compilePlatform() fi echo createZipEmbeddableFileArduino $GOOS $GOARCH $NAME createZipEmbeddableFileArduino $GOOS $GOARCH $NAME - GOOS=$GOOS GOARCH=$GOARCH go-selfupdate $NAME $VERSION + #GOOS=$GOOS GOARCH=$GOARCH go-selfupdate $NAME $VERSION rm -rf $NAME* } diff --git a/installer_icons/Installer.png b/installer_icons/Installer.png new file mode 100644 index 000000000..ccdf286dd Binary files /dev/null and b/installer_icons/Installer.png differ diff --git a/installer_icons/InstallerIcon.png b/installer_icons/InstallerIcon.png new file mode 100644 index 000000000..8951a1a8c Binary files /dev/null and b/installer_icons/InstallerIcon.png differ diff --git a/installer_icons/InstallerSplash.png b/installer_icons/InstallerSplash.png new file mode 100644 index 000000000..0eeeed06c Binary files /dev/null and b/installer_icons/InstallerSplash.png differ diff --git a/installer_icons/tray_iconWin.ico b/installer_icons/tray_iconWin.ico new file mode 100644 index 000000000..a0893f67d Binary files /dev/null and b/installer_icons/tray_iconWin.ico differ diff --git a/main.go b/main.go index 6b1019ee4..fca1eda94 100755 --- a/main.go +++ b/main.go @@ -24,10 +24,12 @@ import ( ) var ( - version = "1.83" - versionFloat = float32(1.83) - addr = flag.String("addr", ":8989", "http service address") - addrSSL = flag.String("addrSSL", ":8990", "https service address") + version = "1.83" + versionFloat = float32(1.83) + embedded_autoupdate = false + embedded_autoextract = false + addr = flag.String("addr", ":8989", "http service address") + addrSSL = flag.String("addrSSL", ":8990", "https service address") //assets = flag.String("assets", defaultAssetPath(), "path to assets") verbose = flag.Bool("v", true, "show debug logging") //verbose = flag.Bool("v", false, "show debug logging") @@ -102,8 +104,8 @@ func (p *program) Stop(s service.Service) error { func main() { svcConfig := &service.Config{ - Name: "ArduinoCreateBridge", - DisplayName: "Arduino Create Bridge", + Name: "ArduinoCreateAgent", + DisplayName: "Arduino Create Agent", Description: "A bridge that allows Arduino Create to operate on the boards connected to the computer", } @@ -125,11 +127,6 @@ func main() { log.Fatal(err) } - err = s.Install() - if err != nil { - logger.Error(err) - } - err = s.Run() if err != nil { logger.Error(err) @@ -137,26 +134,27 @@ func main() { } func startDaemon() { - // setupSysTray() go func() { // autoextract self src, _ := osext.Executable() dest := filepath.Dir(src) - // save the config.ini (if it exists) - if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { - fmt.Println("First run, unzipping self") - err := Unzip(src, dest) - fmt.Println("Self extraction, err:", err) - } + if embedded_autoextract { + // save the config.ini (if it exists) + if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { + fmt.Println("First run, unzipping self") + err := Unzip(src, dest) + fmt.Println("Self extraction, err:", err) + } - if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { - flag.Parse() - fmt.Println("No config.ini at", *configIni) - } else { - flag.Set("config", dest+"/"+*configIni) - iniflags.Parse() + if _, err := os.Stat(dest + "/" + *configIni); os.IsNotExist(err) { + flag.Parse() + fmt.Println("No config.ini at", *configIni) + } else { + flag.Set("config", dest+"/"+*configIni) + iniflags.Parse() + } } // setup logging @@ -167,23 +165,26 @@ func startDaemon() { launchSelfLater() } - var updater = &Updater{ - CurrentVersion: version, - ApiURL: *updateUrl, - BinURL: *updateUrl, - DiffURL: "", - Dir: "update/", - CmdName: *appName, - } + if embedded_autoupdate { - if updater != nil { - go updater.BackgroundRun() - } + var updater = &Updater{ + CurrentVersion: version, + ApiURL: *updateUrl, + BinURL: *updateUrl, + DiffURL: "", + Dir: "update/", + CmdName: *appName, + } + + if updater != nil { + go updater.BackgroundRun() + } - // data, err := Asset("arduino.zip") - // if err != nil { - // log.Println("arduino tools not found") - // } + // data, err := Asset("arduino.zip") + // if err != nil { + // log.Println("arduino tools not found") + // } + } createGlobalConfigMap(&globalConfigMap) @@ -283,7 +284,7 @@ func startDaemon() { log.Fatal("Error ListenAndServe:", err) } }() - + setupSysTray() } var homeTemplate = template.Must(template.New("home").Parse(homeTemplateHtml)) @@ -301,14 +302,18 @@ const homeTemplateHtml = ` var socket; var msg = $("#msg"); - var log = $("#log"); + var log = document.getElementById('log'); + var messages = []; function appendLog(msg) { - var d = log[0] - var doScroll = d.scrollTop == d.scrollHeight - d.clientHeight; - msg.appendTo(log) + messages.push(msg); + if (messages.length > 100) { + messages.shift(); + } + var doScroll = log.scrollTop == log.scrollHeight - log.clientHeight; + log.innerHTML = messages.join("
"); if (doScroll) { - d.scrollTop = d.scrollHeight - d.clientHeight; + log.scrollTop = log.scrollHeight - log.clientHeight; } } @@ -334,7 +339,7 @@ const homeTemplateHtml = ` appendLog($("
Connection closed.
")) }); socket.on("message", function(evt) { - appendLog($("
").text(evt)) + appendLog(evt); }); } else { appendLog($("
Your browser does not support WebSockets.
")) diff --git a/serial.go b/serial.go index 3773e572f..6fb94fd4f 100755 --- a/serial.go +++ b/serial.go @@ -472,24 +472,26 @@ func spListDual(network bool) { // happen on windows in a fallback scenario where an // open port can't be identified because it is locked, // so just solve that by manually inserting - for port := range sh.ports { - - isFound := false - for _, item := range list { - if strings.ToLower(port.portConf.Name) == strings.ToLower(item.Name) { - isFound = true - } - } - - if !isFound { - // artificially push to front of port list - log.Println(fmt.Sprintf("Did not find an open port in the serial port list. We are going to artificially push it onto the list. port:%v", port.portConf.Name)) - var ossp OsSerialPort - ossp.Name = port.portConf.Name - ossp.FriendlyName = port.portConf.Name - list = append([]OsSerialPort{ossp}, list...) - } - } + // if network { + // for port := range sh.ports { + + // isFound := false + // for _, item := range list { + // if strings.ToLower(port.portConf.Name) == strings.ToLower(item.Name) { + // isFound = true + // } + // } + + // if !isFound { + // // artificially push to front of port list + // log.Println(fmt.Sprintf("Did not find an open port in the serial port list. We are going to artificially push it onto the list. port:%v", port.portConf.Name)) + // var ossp OsSerialPort + // ossp.Name = port.portConf.Name + // ossp.FriendlyName = port.portConf.Name + // list = append([]OsSerialPort{ossp}, list...) + // } + // } + // } // we have a full clean list of ports now. iterate thru them // to append the open/close state, baud rates, etc to make diff --git a/seriallist_windows.go b/seriallist_windows.go index a8cea1afa..7fa6a46d3 100644 --- a/seriallist_windows.go +++ b/seriallist_windows.go @@ -6,7 +6,8 @@ import ( "github.com/mattn/go-ole" "github.com/mattn/go-ole/oleutil" //"github.com/tarm/goserial" - "github.com/johnlauer/goserial" + //"github.com/johnlauer/goserial" + "github.com/facchinm/go-serial" "log" "os" "strings" @@ -14,6 +15,7 @@ import ( "strconv" "sync" //"syscall" + "regexp" ) var ( @@ -21,6 +23,7 @@ var ( ) func removeNonArduinoBoards(ports []OsSerialPort) []OsSerialPort { + ports, _ = getList() return ports } @@ -41,10 +44,12 @@ func getList() ([]OsSerialPort, os.SyscallError) { // see if array has any data, if not fallback to the traditional // com port list model - if len(arr) == 0 { - // assume it failed - arr, sysCallErr = getListViaOpen() - } + /* + if len(arr) == 0 { + // assume it failed + arr, sysCallErr = getListViaOpen() + } + */ // see if array has any data, if not fallback to looking at // the registry list @@ -116,6 +121,48 @@ func getListViaWmiPnpEntity() ([]OsSerialPort, os.SyscallError) { list := make([]OsSerialPort, count) for i := 0; i < count; i++ { + + // items we're looping thru look like below and + // thus we can query for any of these names + /* + __GENUS : 2 + __CLASS : Win32_PnPEntity + __SUPERCLASS : CIM_LogicalDevice + __DYNASTY : CIM_ManagedSystemElement + __RELPATH : Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14&0&0002" + __PROPERTY_COUNT : 24 + __DERIVATION : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement} + __SERVER : JOHN-ATIV + __NAMESPACE : root\cimv2 + __PATH : \\JOHN-ATIV\root\cimv2:Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14 + &0&0002" + Availability : + Caption : TinyG v2 (Data Channel) (COM12) + ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318} + CompatibleID : {USB\Class_02&SubClass_02&Prot_01, USB\Class_02&SubClass_02, USB\Class_02} + ConfigManagerErrorCode : 0 + ConfigManagerUserConfig : False + CreationClassName : Win32_PnPEntity + Description : TinyG v2 (Data Channel) + DeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 + ErrorCleared : + ErrorDescription : + HardwareID : {USB\VID_1D50&PID_606D&REV_0097&MI_02, USB\VID_1D50&PID_606D&MI_02} + InstallDate : + LastErrorCode : + Manufacturer : Synthetos (www.synthetos.com) + Name : TinyG v2 (Data Channel) (COM12) + PNPDeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 + PowerManagementCapabilities : + PowerManagementSupported : + Service : usbser + Status : OK + StatusInfo : + SystemCreationClassName : Win32_ComputerSystem + SystemName : JOHN-ATIV + PSComputerName : JOHN-ATIV + */ + // item is a SWbemObject, but really a Win32_Process itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) item := itemRaw.ToIDispatch() @@ -131,16 +178,66 @@ func getListViaWmiPnpEntity() ([]OsSerialPort, os.SyscallError) { s = "COM" + s s = strings.Split(s, ")")[0] list[i].Name = s - list[i].FriendlyName = asString.ToString() //} + + // get the deviceid so we can figure out related ports + // it will look similar to + // USB\VID_1D50&PID_606D&MI_00\6&2F09EA14&0&0000 + deviceIdStr, _ := oleutil.GetProperty(item, "DeviceID") + devIdItems := strings.Split(deviceIdStr.ToString(), "&") + log.Printf("DeviceId elements:%v", devIdItems) + if len(devIdItems) > 3 { + list[i].SerialNumber = devIdItems[3] + list[i].IdProduct = strings.Replace(devIdItems[1], "PID_", "", 1) + list[i].IdVendor = strings.Replace(devIdItems[0], "USB\\VID_", "", 1) + } else { + list[i].SerialNumber = deviceIdStr.ToString() + pidMatch := regexp.MustCompile("PID_(\\d+)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) + if len(pidMatch) > 0 { + if len(pidMatch[0]) > 1 { + list[i].IdProduct = pidMatch[0][1] + } + } + vidMatch := regexp.MustCompile("VID_(\\d+)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) + if len(vidMatch) > 0 { + if len(vidMatch[0]) > 1 { + list[i].IdVendor = vidMatch[0][1] + } + } + } + + if list[i].IdVendor != "2341" { + list[i].FriendlyName = asString.ToString() + } else { + archBoardName, boardName, _ := getBoardName("0x" + list[i].IdProduct) + list[i].RelatedNames = append(list[i].RelatedNames, archBoardName) + list[i].FriendlyName = strings.Trim(boardName, "\n") + } + + manufStr, _ := oleutil.GetProperty(item, "Manufacturer") + list[i].Manufacturer = manufStr.ToString() + descStr, _ := oleutil.GetProperty(item, "Description") + list[i].Product = descStr.ToString() + //classStr, _ := oleutil.GetProperty(item, "CreationClassName") + //list[i].DeviceClass = classStr.ToString() + } - /* - for index, element := range list { - log.Println("index ", index, " element ", element.Name+ - " friendly ", element.FriendlyName) + for index, element := range list { + + log.Printf("index:%v, name:%v, friendly:%v ", index, element.Name, element.FriendlyName) + + for index2, element2 := range list { + if index == index2 { + continue + } + if element.SerialNumber == element2.SerialNumber { + log.Printf("Found related element1:%v, element2:%v", element, element2) + list[index].RelatedNames = append(list[index].RelatedNames, element2.Name) + } } - */ + + } return list, err } @@ -153,8 +250,13 @@ func getListViaOpen() ([]OsSerialPort, os.SyscallError) { var igood int = 0 for i := 0; i < 100; i++ { prtname := "COM" + strconv.Itoa(i) - conf := &serial.Config{Name: prtname, Baud: 9600} - sp, err := serial.OpenPort(conf) + //conf := &serial.Config{Name: prtname, Baud: 1200} + mode := &serial.Mode{ + BaudRate: 1200, + Vmin: 0, + Vtimeout: 10, + } + sp, err := serial.OpenPort(prtname, mode) //log.Println("Just tried to open port", prtname) if err == nil { //log.Println("Able to open port", prtname) diff --git a/trayicon.go b/trayicon.go index ad6aa73b5..0d2cd58cf 100644 --- a/trayicon.go +++ b/trayicon.go @@ -46,9 +46,12 @@ func setupSysTray() { func setupSysTrayReal() { systray.SetIcon(icon.Data) - mUrl := systray.AddMenuItem("Go to create.arduino.cc", "Arduino Create") + mUrl := systray.AddMenuItem("Go to Create (staging)", "Arduino Create") + menuVer := systray.AddMenuItem("Agent version "+version, "") mQuit := systray.AddMenuItem("Quit", "Quit the bridge") + menuVer.Disable() + go func() { <-mQuit.ClickedCh systray.Quit() @@ -59,6 +62,6 @@ func setupSysTrayReal() { // We can manipulate the systray in other goroutines go func() { <-mUrl.ClickedCh - open.Run("http://create.arduino.cc") + open.Run("http://create-staging.arduino.cc") }() } diff --git a/utilities.go b/utilities.go index 4fa096825..d71620674 100644 --- a/utilities.go +++ b/utilities.go @@ -129,7 +129,6 @@ func pipe_commands(commands ...*exec.Cmd) ([]byte, error) { commands[i].Stderr = &errorBuffer if err := call(commands, pipeStack); err != nil { - logger.Errorf(string(errorBuffer.Bytes()), err) return nil, err }