From 7d598fd861648740ebd17c2dd5fc0d1536c4ce5b Mon Sep 17 00:00:00 2001 From: Adrian Zankich Date: Wed, 23 Oct 2013 22:00:03 -0700 Subject: [PATCH] More WIP of base structs --- src/gobot/adaptor.go | 86 +++++++++++++++++++++++++++++++++++++++++ src/gobot/connection.go | 77 ++++++++++++++++++++++++++++++------ src/gobot/device.go | 68 +++++++++++++++++++++++++------- src/gobot/driver.go | 66 +++++++++++++++++++++++++++++++ src/gobot/gobot.go | 11 +++++- src/gobot/port.go | 83 +++++++++++++++++++++++++++++++++++++++ src/gobot/robot.go | 68 +++++++++++++++++++++++--------- 7 files changed, 413 insertions(+), 46 deletions(-) diff --git a/src/gobot/adaptor.go b/src/gobot/adaptor.go index 8b7648ce..5f06ac73 100644 --- a/src/gobot/adaptor.go +++ b/src/gobot/adaptor.go @@ -1 +1,87 @@ package gobot + +type Adaptor struct { + Name string + Robot Robot + Connected bool + Port Port + Params map[string]string +} + +func (Adaptor) NewAdaptor(a Adaptor) Adaptor { + return a +} + +// Closes connection with device if connected +// @return [Boolean] +func (a *Adaptor) Finalize() bool{ + if a.IsConnected() { + a.Disconnect() + } + return true +} + +// Makes connected flag true +// @return [Boolean] +func (a *Adaptor) Connect() bool { + a.Connected = true + return true +} + +// Makes connected flag false +// @return [Boolean] +func (a *Adaptor) Disconnect() bool { + a.Connected = false + return true +} + +// Makes connected flag true +// @return [Boolean] true unless connected +func (a *Adaptor) Reconnect() bool { + if !a.IsConnected(){ + return a.Connect() + } + return true +} + +// @return [Boolean] connected flag status +func (a *Adaptor) IsConnected() bool { + return a.Connected +} + +/* +# Connects to configured port +# @return [TCPSocket] tcp socket of tcp port +# @return [String] port configured +def connect_to + if port.is_tcp? + connect_to_tcp + else + port.port + end +end + +# @return [TCPSocket] TCP socket connection +def connect_to_tcp + @socket ||= TCPSocket.new(port.host, port.port) +end + +# @return [UDPSocket] UDP socket connection +def connect_to_udp + @udp_socket ||= UDPSocket.new +end + +# Creates serial connection +# @param speed [int] +# @param data_bits [int] +# @param stop_bits [int] +# @param parity +# @return [SerialPort] new connection +def connect_to_serial(speed=57600, data_bits=8, stop_bits=1, parity=nil) + require 'serialport' + parity = ::SerialPort::NONE unless parity + @sp = ::SerialPort.new(port.port, speed, data_bits, stop_bits, parity) +rescue LoadError + Logger.error "Please 'gem install hybridgroup-serialport' for serial port support." +end +*/ \ No newline at end of file diff --git a/src/gobot/connection.go b/src/gobot/connection.go index 7fd168ac..d5a8d78b 100644 --- a/src/gobot/connection.go +++ b/src/gobot/connection.go @@ -1,23 +1,78 @@ package gobot -import "fmt" +import ( + "fmt" + "math/rand" + "time" +) type Connection struct { - Connection_id string + ConnectionId string Name string Adaptor string Port string - Parent string + Params map[string]string + Robot Robot } -//func (c *Connection) New(c Connection) *Connection { -// return c -//} - -func (c *Connection) Connect() { - fmt.Println("Connecting to "+ c.Name + " on port " + c.Port + "...") +type ConnectionType struct { + ConnectionId string + Name string + Adaptor Adaptor + Port Port + Robot Robot + Params map[string]string } -func (c *Connection) Disconnect() { - fmt.Println("Diconnecting from "+ c.Name + " on port " + c.Port + "...") +func NewConnection(c Connection) *ConnectionType { + ct := new(ConnectionType) + if c.ConnectionId == "" { + rand.Seed( time.Now().UTC().UnixNano()) + i := rand.Int() + ct.ConnectionId = fmt.Sprintf("%v", i) + } else { + ct.ConnectionId = c.ConnectionId + } + ct.Name = c.Name + //ct.Port = Port.New(c.Port) + ct.Robot = c.Robot + ct.Params = c.Params + ct.Adaptor = Adaptor{ Port: ct.Port, Robot: ct.Robot, Params: ct.Params, } + + return ct } + +func (ct *ConnectionType) Connect() { + fmt.Println("Connecting to "+ ct.Name + " on port " + ct.Port.ToString() + "...") + ct.Adaptor.Connect() +} + +func (ct *ConnectionType) Disconnect() { + fmt.Println("Diconnecting from "+ ct.Name + " on port " + ct.Port.ToString() + "...") + ct.Adaptor.Disconnect() +} + +// @return [Boolean] Connection status +func (ct *ConnectionType) IsConnected() bool { + return ct.Adaptor.IsConnected() +} + +// @return [String] Adaptor class name +func (ct *ConnectionType) AdaptorName() string { + return ct.Adaptor.Name +} + +// # Redirects missing methods to adaptor, +// # attemps reconnection if adaptor not connected +// def method_missing(method_name, *arguments, &block) +// unless adaptor.connected? +// Logger.warn "Cannot call unconnected adaptor '#{name}', attempting to reconnect..." +// adaptor.reconnect +// return nil +// end +// adaptor.send(method_name, *arguments, &block) +// rescue Exception => e +// Logger.error e.message +// Logger.error e.backtrace.inspect +// return nil +// end diff --git a/src/gobot/device.go b/src/gobot/device.go index b1c73692..2460591f 100644 --- a/src/gobot/device.go +++ b/src/gobot/device.go @@ -1,32 +1,70 @@ package gobot -import "fmt" +import ( + "fmt" + "strconv" +) type Device struct { Name string Pin string - Parent string Connection string Interval string Driver string + Params map[string]string + Robot Robot } -//func (d *Device) New() *Device{ -// return d -//} +type DeviceType struct { + Name string + Pin string + Robot Robot + Connection ConnectionType + Interval float64 + Driver Driver + Params map[string]string +} -func (d *Device) Start() { - fmt.Println("Device " + d.Name + "started") +func NewDevice(d Device) *DeviceType { + dt := new(DeviceType) + dt.Name = d.Name + dt.Pin = d.Pin + dt.Robot = d.Robot + dt.Params = d.Params +// dt.Connection = determine_connection(params[:connection]) || default_connection + dt.Connection = ConnectionType{Name: d.Connection,} + if d.Interval == "" { + dt.Interval = 0.5 + } else { + f, err := strconv.ParseFloat(d.Interval, 64) + if err == nil { + dt.Interval = f + } else { + fmt.Println(err) + dt.Interval = 0.5 + } + } + + //dt.Driver = Driver.New(Driver{Robot: d.Robot, Params: d.Params,}) + return dt +} + +func (dt *DeviceType) Start() { + fmt.Println("Device " + dt.Name + "started") + dt.Driver.Start() } -func (d *Device) determineConnection(c Connection){ - //d.Parent.connections(c) if c -} -func (d *Device) defaultConnection() { - //d.Parent.connections.first -} +// def publish(event, *data) +// if data.first +// driver.publish(event_topic_name(event), *data) +// else +// driver.publish(event_topic_name(event)) +// end +// end -func requireDriver(driverName string) { - fmt.Println("dynamic load driver" + driverName) + +// Execute driver command +func (dt *DeviceType) Command(method_name string, arguments []string) { + //dt.Driver.Command(method_name, arguments) } diff --git a/src/gobot/driver.go b/src/gobot/driver.go index 8b7648ce..fcd4fb4c 100644 --- a/src/gobot/driver.go +++ b/src/gobot/driver.go @@ -1 +1,67 @@ package gobot + +import "fmt" + +type Driver struct { + Name string + Robot Robot + Params map[string]string +} + +func NewDriver(d Driver) Driver { + return d +} + +// @return [Connection] parent connection +func (d *Driver) Connection() Connection { + return d.Robot.Connections[0] +} + +// @return [String] parent pin +func (d *Driver) pin() string { + return d.Robot.Devices[0].Pin +} + +// @return [String] parent interval +func (d *Driver) Interval() string { + return d.Robot.Devices[0].Interval +} + +// Generic driver start +func (d *Driver) Start() { + fmt.Println("Starting driver " + d.Name + "...") +} + +// @return [String] parent topic name +//func eventTopicName(event) { +// parent.event_topic_name(event) +//} + +// @return [Collection] commands +//func commands() { +// self.class.const_get('COMMANDS') +//} + +// Execute command +// @param [Symbol] method_name +// @param [Array] arguments +//func command(method_name, *arguments) { +// known_command?(method_name) +// if arguments.first +// self.send(method_name, *arguments) +// else +// self.send(method_name) +// end +// rescue Exception => e +// Logger.error e.message +// Logger.error e.backtrace.inspect +// return nil +//} + +// @return [Boolean] True if command exists +//func isKnownCommand(method_name) { +// return true if commands.include?(method_name.intern) +// +// Logger.warn("Calling unknown command '#{method_name}'...") +// return false +//} diff --git a/src/gobot/gobot.go b/src/gobot/gobot.go index 05e53c85..1f78b98e 100644 --- a/src/gobot/gobot.go +++ b/src/gobot/gobot.go @@ -12,11 +12,18 @@ import ( // Work func() //} -func Every(t time.Duration, ret func()) { +func Every(t time.Duration, f func()) { go func(){ for{ - ret() time.Sleep(t) + f() } }() +} + +func After(t time.Duration, f func()) { + go func(){ + time.Sleep(t) + f() + }() } \ No newline at end of file diff --git a/src/gobot/port.go b/src/gobot/port.go index 8b7648ce..956e3e51 100644 --- a/src/gobot/port.go +++ b/src/gobot/port.go @@ -1 +1,84 @@ package gobot + +type Port struct { + Name string +} + +func (Port) NewPort(p string) *Port{ + return new(Port) +} + +func (p *Port) ToString() string { + return p.Name +} +/* +module Artoo + # The Artoo::Port class represents port and/or host to be used to connect + # tp a specific individual hardware device. + class Port + attr_reader :port, :host + + # Create new port + # @param [Object] data + def initialize(data=nil) + @is_tcp, @is_serial, @is_portless = false + parse(data) + end + + # @return [Boolean] True if serial port + def is_serial? + @is_serial == true + end + + # @return [Boolean] True if tcp port + def is_tcp? + @is_tcp == true + end + + # @return [Boolean] True if does not have real port + def is_portless? + @is_portless == true + end + + # @return [String] port + def to_s + if is_portless? + "none" + elsif is_serial? + port + else + "#{host}:#{port}" + end + end + + private + + def parse(data) + case + # portless + when data.nil? + @port = nil + @is_portless = true + + # is TCP host/port? + when m = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d{1,5})/.match(data) + @port = m[2] + @host = m[1] + @is_tcp = true + + # is it a numeric port for localhost tcp? + when /^[0-9]{1,5}$/.match(data) + @port = data + @host = "localhost" + @is_tcp = true + + # must be a serial port + else + @port = data + @host = nil + @is_serial = true + end + end + end +end +*/ \ No newline at end of file diff --git a/src/gobot/robot.go b/src/gobot/robot.go index 62ddc330..b5f0c2ba 100644 --- a/src/gobot/robot.go +++ b/src/gobot/robot.go @@ -6,8 +6,8 @@ import ( "math/rand" ) -var connectionTypes []Connection -var deviceTypes []Device +var connectionTypes []*ConnectionType +var deviceTypes []*DeviceType type Robot struct { Connections []Connection @@ -22,35 +22,35 @@ func (r *Robot) Start() { i := rand.Int() r.Name = fmt.Sprintf("Robot %v", i) } - initConnections(r.Connections) - initDevices(r.Devices) - startConnections() - startDevices() + r.initConnections(r.Connections) + r.initDevices(r.Devices) + r.startConnections() + r.startDevices() r.Work() for{time.Sleep(1 * time.Second)} } -func initConnections(connections []Connection) { - connectionTypes := make([]Connection, len(connections)) +func (r *Robot) initConnections(connections []Connection) { + connectionTypes := make([]*ConnectionType, len(connections)) fmt.Println("Initializing connections...") for i := range connections { fmt.Println("Initializing connection " + connections[i].Name + "...") -// connectionTypes[i] = Connection.New(connections[i]) - connectionTypes[i] = connections[i] + connections[i].Robot = *r + connectionTypes[i] = NewConnection(connections[i]) } } -func initDevices(devices []Device) { - deviceTypes := make([]Device, len(devices)) +func (r *Robot) initDevices(devices []Device) { + deviceTypes := make([]*DeviceType, len(devices)) fmt.Println("Initializing devices...") for i := range devices { - fmt.Println("Initializing donnection " + devices[i].Name + "...") -// deviceTypes[i] = Device.New(devices[i]) - deviceTypes[i] = devices[i] + fmt.Println("Initializing device " + devices[i].Name + "...") + devices[i].Robot = *r + deviceTypes[i] = NewDevice(devices[i]) } } -func startConnections() { +func (r *Robot) startConnections() { fmt.Println("Starting connections...") for i := range connectionTypes { fmt.Println("Starting connection " + connectionTypes[i].Name + "...") @@ -58,10 +58,42 @@ func startConnections() { } } -func startDevices() { +func (r *Robot) startDevices() { fmt.Println("Starting devices...") for i := range deviceTypes { - fmt.Println("Starting devices " + deviceTypes[i].Name + "...") + fmt.Println("Starting device " + deviceTypes[i].Name + "...") deviceTypes[i].Start() } } +// # Terminate all connections +// def disconnect +// connections.each {|k, c| c.async.disconnect} +// end + +// # @return [Connection] default connection +// def default_connection +// connections.values.first +// end + +// # @return [Collection] connection types +// def connection_types +// current_class.connection_types ||= [{:name => :passthru}] +// end + +// # @return [Collection] device types +// def device_types +// current_class.device_types ||= [] +// current_class.device_types +// end + +// # @return [Proc] current working code +// def working_code +// current_class.working_code ||= proc {puts "No work defined."} +// end + +// # @param [Symbol] period +// # @param [Numeric] interval +// # @return [Boolean] True if there is recurring work for the period and interval +// def has_work?(period, interval) +// current_instance.timers.find {|t| t.recurring == (period == :every) && t.interval == interval} +// end