Return-Path: X-Original-To: apmail-mynewt-commits-archive@minotaur.apache.org Delivered-To: apmail-mynewt-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 7157E18C9E for ; Tue, 15 Dec 2015 06:46:11 +0000 (UTC) Received: (qmail 92472 invoked by uid 500); 15 Dec 2015 06:46:11 -0000 Delivered-To: apmail-mynewt-commits-archive@mynewt.apache.org Received: (qmail 92446 invoked by uid 500); 15 Dec 2015 06:46:11 -0000 Mailing-List: contact commits-help@mynewt.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@mynewt.incubator.apache.org Delivered-To: mailing list commits@mynewt.incubator.apache.org Received: (qmail 92436 invoked by uid 99); 15 Dec 2015 06:46:11 -0000 Received: from Unknown (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Dec 2015 06:46:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id D2032C0CEF for ; Tue, 15 Dec 2015 06:46:10 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.227 X-Spam-Level: * X-Spam-Status: No, score=1.227 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.554, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-east.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id buayrnDBrXbJ for ; Tue, 15 Dec 2015 06:46:00 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-east.apache.org (ASF Mail Server at mx1-us-east.apache.org) with SMTP id CB986429C7 for ; Tue, 15 Dec 2015 06:45:59 +0000 (UTC) Received: (qmail 92414 invoked by uid 99); 15 Dec 2015 06:45:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 15 Dec 2015 06:45:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 16356DFF6F; Tue, 15 Dec 2015 06:45:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: sterling@apache.org To: commits@mynewt.incubator.apache.org Date: Tue, 15 Dec 2015 06:45:59 -0000 Message-Id: <2153e89fcc7c4fb0bfea89bf631170de@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] incubator-mynewt-newt git commit: add nmgr echo command support and make it work Repository: incubator-mynewt-newt Updated Branches: refs/heads/master 5785e365f -> 34aa1f48e add nmgr echo command support and make it work Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/34aa1f48 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/34aa1f48 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/34aa1f48 Branch: refs/heads/master Commit: 34aa1f48eb8ba977ef4f77dc8e0d6ee4f87f8b75 Parents: 1938fa4 Author: Sterling Hughes Authored: Mon Dec 14 22:45:19 2015 -0800 Committer: Sterling Hughes Committed: Mon Dec 14 22:45:37 2015 -0800 ---------------------------------------------------------------------- newtmgr/newtmgr.go | 70 ++++++++++++++++++++++++++++-------- newtmgr/protocol/cmdrunner.go | 13 ++++--- newtmgr/protocol/echo.go | 50 ++++++++++++++++++++++++++ newtmgr/protocol/nmgr.go | 19 ++++++---- newtmgr/protocol/stats.go | 4 --- newtmgr/transport/conn.go | 6 +++- newtmgr/transport/connserial.go | 60 ++++++++++++++++++------------- 7 files changed, 165 insertions(+), 57 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/newtmgr.go ---------------------------------------------------------------------- diff --git a/newtmgr/newtmgr.go b/newtmgr/newtmgr.go index 02f0ffa..e9b5bc1 100644 --- a/newtmgr/newtmgr.go +++ b/newtmgr/newtmgr.go @@ -17,20 +17,36 @@ package main import ( "fmt" + "log" + "os" + "strings" + "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/cli" "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/protocol" "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/transport" "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/util" + "github.com/hashicorp/logutils" "github.com/spf13/cobra" - "os" - "strings" ) var ConnProfileName string +var LogLevel string = "WARN" + +func setupLog() { + filter := &logutils.LevelFilter{ + Levels: []logutils.LogLevel{"DEBUG", "VERBOSE", "INFO", + "WARN", "ERROR"}, + MinLevel: logutils.LogLevel(LogLevel), + Writer: os.Stderr, + } + + log.SetOutput(filter) +} func nmUsage(cmd *cobra.Command, err error) { if err != nil { sErr := err.(*util.NewtError) + fmt.Printf("ERROR: %s\n", err.Error()) fmt.Fprintf(os.Stderr, "[DEBUG] %s", sErr.StackTrace) } @@ -163,18 +179,18 @@ func connProfileCmd() *cobra.Command { return cpCmd } -func statShowCmd(cmd *cobra.Command, args []string) { +func echoRunCmd(cmd *cobra.Command, args []string) { cpm, err := cli.NewCpMgr() if err != nil { nmUsage(cmd, err) } - cp, err := cpm.GetConnProfile(ConnProfileName) + profile, err := cpm.GetConnProfile(ConnProfileName) if err != nil { nmUsage(cmd, err) } - conn, err := transport.NewConn(cp) + conn, err := transport.NewConn(profile) if err != nil { nmUsage(cmd, err) } @@ -184,22 +200,42 @@ func statShowCmd(cmd *cobra.Command, args []string) { nmUsage(cmd, err) } - stats, err := runner.Read(protocol.Stats) + echo, err := protocol.NewEcho() + if err != nil { + nmUsage(cmd, err) + } + + echo.Message = args[0] + + nmr, err := echo.EncodeWriteRequest() + if err != nil { + nmUsage(cmd, err) + } + + if err := runner.WriteReq(nmr); err != nil { + nmUsage(cmd, err) + } + + rsp, err := runner.ReadReq() if err != nil { nmUsage(cmd, err) } - stats.Display() + ersp, err := protocol.DecodeEchoResponse(rsp.Data) + if err != nil { + nmUsage(cmd, err) + } + fmt.Println(ersp.Message) } -func statCmd() *cobra.Command { - statCmd := &cobra.Command{ - Use: "stat", - Short: "Display statistics from a remote newtmgr device", - Run: statShowCmd, +func echoCmd() *cobra.Command { + echoCmd := &cobra.Command{ + Use: "echo", + Short: "Send data to remote endpoint using newtmgr, and receive data back", + Run: echoRunCmd, } - return statCmd + return echoCmd } func parseCmds() *cobra.Command { @@ -211,16 +247,20 @@ func parseCmds() *cobra.Command { }, } - nmCmd.PersistentFlags().StringVar(&ConnProfileName, "conn", "c", "", + nmCmd.PersistentFlags().StringVarP(&ConnProfileName, "conn", "c", "", "connection profile to use.") + nmCmd.PersistentFlags().StringVarP(&LogLevel, "loglevel", "l", "", + "log level to use (default WARN.)") + nmCmd.AddCommand(connProfileCmd()) - nmCmd.AddCommand(statCmd()) + nmCmd.AddCommand(echoCmd()) return nmCmd } func main() { cmd := parseCmds() + setupLog() cmd.Execute() } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/protocol/cmdrunner.go ---------------------------------------------------------------------- diff --git a/newtmgr/protocol/cmdrunner.go b/newtmgr/protocol/cmdrunner.go index 1451f5c..fd4edec 100644 --- a/newtmgr/protocol/cmdrunner.go +++ b/newtmgr/protocol/cmdrunner.go @@ -16,12 +16,13 @@ package protocol import ( - "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/protocol" + "log" + "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/transport" ) type CmdRunner struct { - conn *transport.Conn + conn transport.Conn } func (cr *CmdRunner) ReadReq() (*NmgrReq, error) { @@ -41,26 +42,28 @@ func (cr *CmdRunner) ReadReq() (*NmgrReq, error) { func (cr *CmdRunner) WriteReq(nmr *NmgrReq) error { data := []byte{} + log.Printf("[DEBUG] Writing netmgr request %s", nmr) + data, err := nmr.SerializeRequest(data) if err != nil { return err } - pkt, err := NewPacket(len(data)) + pkt, err := transport.NewPacket(uint16(len(data))) if err != nil { return err } pkt.AddBytes(data) - if err := cr.conn.Write(pkt); err != nil { + if err := cr.conn.WritePacket(pkt); err != nil { return err } return nil } -func NewCmdRunner(conn *transport.Conn) (*CmdRunner, error) { +func NewCmdRunner(conn transport.Conn) (*CmdRunner, error) { cmd := &CmdRunner{ conn: conn, } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/protocol/echo.go ---------------------------------------------------------------------- diff --git a/newtmgr/protocol/echo.go b/newtmgr/protocol/echo.go new file mode 100644 index 0000000..c00cb68 --- /dev/null +++ b/newtmgr/protocol/echo.go @@ -0,0 +1,50 @@ +/* + Copyright 2015 Runtime Inc. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package protocol + +type Echo struct { + Message string +} + +func NewEcho() (*Echo, error) { + s := &Echo{} + return s, nil +} + +func (e *Echo) EncodeWriteRequest() (*NmgrReq, error) { + data := []byte(e.Message) + + nmr, err := NewNmgrReq() + if err != nil { + return nil, err + } + + nmr.Op = NMGR_OP_WRITE + nmr.Flags = 0 + nmr.Group = 0 + nmr.Id = 0 + nmr.Len = uint16(len(data)) + nmr.Data = data + + return nmr, nil +} + +func DecodeEchoResponse(data []byte) (*Echo, error) { + e := &Echo{} + e.Message = string(data[:]) + + return e, nil +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/protocol/nmgr.go ---------------------------------------------------------------------- diff --git a/newtmgr/protocol/nmgr.go b/newtmgr/protocol/nmgr.go index 1e5e910..848cfc3 100644 --- a/newtmgr/protocol/nmgr.go +++ b/newtmgr/protocol/nmgr.go @@ -17,6 +17,10 @@ package protocol import ( "encoding/binary" + "fmt" + "log" + + "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/util" ) type NmgrReq struct { @@ -44,8 +48,8 @@ func NewNmgrReq() (*NmgrReq, error) { func DeserializeNmgrReq(data []byte) (*NmgrReq, error) { if len(data) < 8 { - return nil, util.NewNewtError("Newtmgr request buffer too small " + - len(data) + " bytes.") + return nil, util.NewNewtError(fmt.Sprintf( + "Newtmgr request buffer too small %d bytes", len(data))) } nmr := &NmgrReq{} @@ -61,17 +65,18 @@ func DeserializeNmgrReq(data []byte) (*NmgrReq, error) { return nil, util.NewNewtError("Newtmgr request length doesn't " + "match data length.") } - - copy(nmr.Data, data) + nmr.Data = data return nmr, nil } func (nmr *NmgrReq) SerializeRequest(data []byte) ([]byte, error) { - u16b := []byte{} + log.Printf("[DEBUG] Serializing request %s into buffer %s", nmr, data) + + u16b := make([]byte, 2) - data = append(data, nmr.Op.(byte)) - data = append(data, nmr.Flags.(byte)) + data = append(data, byte(nmr.Op)) + data = append(data, byte(nmr.Flags)) binary.BigEndian.PutUint16(u16b, nmr.Len) data = append(data, u16b...) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/protocol/stats.go ---------------------------------------------------------------------- diff --git a/newtmgr/protocol/stats.go b/newtmgr/protocol/stats.go index f1d5f21..04ea924 100644 --- a/newtmgr/protocol/stats.go +++ b/newtmgr/protocol/stats.go @@ -15,8 +15,6 @@ package protocol -var Stats, _ = NewStats() - type Stats struct { } @@ -24,5 +22,3 @@ func NewStats() (*Stats, error) { s := &Stats{} return s, nil } - -func (s *Stats) EncodeRequest() http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/transport/conn.go ---------------------------------------------------------------------- diff --git a/newtmgr/transport/conn.go b/newtmgr/transport/conn.go index 37d57d8..e2d2ece 100644 --- a/newtmgr/transport/conn.go +++ b/newtmgr/transport/conn.go @@ -17,12 +17,13 @@ package transport import ( "bytes" + "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/cli" "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/util" ) type Conn interface { - Open(cp *ConnProfile) error + Open(cp *cli.ConnProfile) error ReadPacket() (*Packet, error) WritePacket(pkt *Packet) error } @@ -62,6 +63,9 @@ func NewConn(cp *cli.ConnProfile) (Conn, error) { switch cp.Type { case "serial": c = &ConnSerial{} + if err := c.Open(cp); err != nil { + return nil, err + } default: return nil, util.NewNewtError("Invalid conn profile " + cp.Type + " not implemented") http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/34aa1f48/newtmgr/transport/connserial.go ---------------------------------------------------------------------- diff --git a/newtmgr/transport/connserial.go b/newtmgr/transport/connserial.go index 09ece25..26a193f 100644 --- a/newtmgr/transport/connserial.go +++ b/newtmgr/transport/connserial.go @@ -19,10 +19,12 @@ import ( "bufio" "encoding/base64" "encoding/binary" + "fmt" + "log" + "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/newtmgr/cli" "git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/util" - "github.com/jacobsa/go-serial/serial" - "io" + "github.com/tarm/serial" ) type ConnSerial struct { @@ -30,25 +32,22 @@ type ConnSerial struct { currentPacket *Packet scanner *bufio.Scanner - serialChannel io.ReadWriteCloser + serialChannel *serial.Port } func (cs *ConnSerial) Open(cp *cli.ConnProfile) error { var err error - opts := serial.OpenOptions{ - PortName: cp.ConnString, - BaudRate: 9600, - DataBits: 8, - StopBits: 1, - MinimumReadSize: 1, + c := &serial.Config{ + Name: cp.ConnString, + Baud: 9600, } - cs.serialChannel, err = serial.Open(opts) + cs.serialChannel, err = serial.OpenPort(c) if err != nil { return util.NewNewtError(err.Error()) } - defer cs.serialChannel.Close() + //defer cs.serialChannel.Close() // Most of the reading will be done line by line, use the // bufio.Scanner to do this @@ -60,27 +59,27 @@ func (cs *ConnSerial) Open(cp *cli.ConnProfile) error { func (cs *ConnSerial) ReadPacket() (*Packet, error) { scanner := cs.scanner for scanner.Scan() { - line := scanner.Text() + line := []byte(scanner.Text()) if len(line) < 2 || ((line[0] != 4 || line[1] != 20) && (line[0] != 6 || line[1] != 9)) { continue } - base64Data := line[2:] + base64Data := string(line[2:]) data, err := base64.StdEncoding.DecodeString(base64Data) if err != nil { - return nil, util.NewNewtError("Couldn't decode base64 string: " + - line) + return nil, util.NewNewtError(fmt.Sprintf("Couldn't decode base64 string: %b", + line)) } - if line[0] == 4 && line[1] == 20 { + if line[0] == 6 && line[1] == 9 { if len(data) < 2 { continue } - pktLen := binary.LittleEndian.Uint16(data[0:2]) + pktLen := binary.BigEndian.Uint16(data[0:2]) cs.currentPacket, err = NewPacket(pktLen) if err != nil { return nil, err @@ -88,6 +87,10 @@ func (cs *ConnSerial) ReadPacket() (*Packet, error) { data = data[2:] } + if cs.currentPacket == nil { + continue + } + full := cs.currentPacket.AddBytes(data) if full { pkt := cs.currentPacket @@ -96,34 +99,41 @@ func (cs *ConnSerial) ReadPacket() (*Packet, error) { } } - return nil, nil + return nil, util.NewNewtError("Scanning incoming data failed") +} + +func (cs *ConnSerial) writeData(bytes []byte) { + log.Printf("[DEBUG] Writing %b to data channel", bytes) + cs.serialChannel.Write(bytes) } func (cs *ConnSerial) WritePacket(pkt *Packet) error { data := pkt.GetBytes() dLen := uint16(len(data)) - base64Data := []byte{} - pktData := []byte{} + pktData := make([]byte, 2) - binary.LittleEndian.PutUint16(pktData, dLen) + binary.BigEndian.PutUint16(pktData, dLen) pktData = append(pktData, data...) + base64Data := make([]byte, base64.StdEncoding.EncodedLen(len(pktData))) + base64.StdEncoding.Encode(base64Data, pktData) written := 0 totlen := len(base64Data) + for written < totlen { if written == 0 { - cs.serialChannel.Write([]byte{4, 20}) + cs.writeData([]byte{6, 9}) } else { - cs.serialChannel.Write([]byte{6, 9}) + cs.writeData([]byte{4, 20}) } writeLen := util.Min(122, totlen) writeBytes := base64Data[:writeLen] - cs.serialChannel.Write(writeBytes) - cs.serialChannel.Write([]byte{'\n'}) + cs.writeData(writeBytes) + cs.writeData([]byte{'\n'}) written += writeLen }