Commit 00db8886 authored by Mattias Fält's avatar Mattias Fält
Browse files

Initial commit, not tested

parent 2d2def46
# Devices should define a type `T` with methods:
# write!(::T, identifier, val)
# read(::T, identifier)
include("SysLED.jl")
#List of available devices and their constructors
const DEVICES = Dict("sysled" => SysLED()]
"""
dev = getdev(devname)
Gets the device corresponding to the name `devname`
"""
function getdev(devname)
dev = try
DEVICES[devname]
catch
error("Device $devname does not exist")
end
return dev
end
"""
bbparse(cmd)
Parse and execute the command `cmd`
"""
bbparse(any) = error("Unexpected input: $any")
"""
bbparse(l::Tuple)
Parse input on the form `l=(iswrite, ndev, cmd1, cmd2, ..., cmdn)``
where if `iswrite`
`cmdi = (devname, id, val)`
and if not `iswrite`
`cmdi = (devname, id)`
"""
function bbparse(l::Tuple)
iswrite = l[1]::Bool #True if write command, false if read
ndev = l[2]::Int32 #Number of devices/commands
for i = 1:ndev
command = l[2+i]::Tuple
dev = getdev(devname)
if iswrite
write!(dev, command[2], command[3])
else
val = read(dev, command[2])
println("val")
#TODO return somewhere
end
end
end
"""
run_server(port=2001)
Run a server on `port` that listens for commands from computer
"""
function run_server(port=2001)
server = listen(port)
@async while isopen(server)
sock = accept(server)
@async while isopen(sock)
l = deserialize(sock); println("deserialize: $l")
bbparse(l)
end
end
return server
end
"""
The on-board leds with id ∈ [1,2,3,4]
"""
struct SysLED
end
function write!(::SysLED, ind::Int32, val::Bool)
ind [1,2,3,4] && error("Invalid SysLEND ind: $ind")
filename = "/sys/class/leds/beaglebone:green:usr$(ind-1)"
file = open(filename, "w+")
write(file, val ? "1" : "0")
close(file)
return
end
function read(::SysLED, ind::Int32)
ind [1,2,3,4] && error("Invalid SysLEND ind: $ind")
filename = "/sys/class/leds/beaglebone:green:usr$(ind-1)"
file = open(filename, "r")
l = readline(file, val)
(l != "1" && l != "0") && error("Invalid value \"$l\" read from SysLed")
close(file)
return l == "1"
end
struct BeagleBoneStream <: LabStream
devices::Device
stream::TCPSocket
end
function BeagleBoneStream(addr::IPAddr, port::Int64=2001)
clientside = connect(addr, port)
BeagleBoneStream(Device[], clientside)
end
#For BeagleBoneStream we can directly serialize the data, other streams might want to send binary data
serialize(bbstream::BeagleBoneStream, cmd) = serialize(bbstream.stream, cmd)
function init_devices!(bbstream::BeagleBoneStream, devs::Device...)
for dev in devs
if dev bbstream.devices
setstream!(dev, bbstream)
append!(bbstream.devices, dev)
initialize(dev)
else
warn("Device $dev already added to a stream")
end
end
return
end
function send!(stream::BeagleBoneStream)
cmds = Tuple[]
for dev in stream.devices
val = getsetvalue(dev)
devstream, cmd = safe_getwritecommand(dev, val)
devstream == stream || error("Device $dev is connected to other stream $devstream")
push!(cmds, cmd)
end
ncmds = length(cmds)
if ncmds > 0
allcmds = (true, ncmds, cmds...)
println("Sending command: $allcmds")
serialize(stream, allcmds)
end
return
end
function read(stream::BeagleBoneStream)
cmds = Tuple[]
for dev in stream.devices
devstream, cmd = safe_getreadcommand(dev)
devstream == stream || error("Device $dev is connected to other stream $devstream")
push!(cmds, cmd)
end
ncmds = length(cmds)
if ncmds > 0
allcmds = (false, ncmds, cmds...)
println("Sending command: $allcmds")
serialize(stream, allcmds)
#TODO save values in dev
# update_read_vale!(dev, val)
end
return
end
function init_devices!(bbstream::BeagleBoneStream, devs::Device...)
for dev in devs
if dev bbstream.devices
setstream!(dev, bbstream)
append!(bbstream.devices, dev)
initialize(dev)
else
warn("Device $dev already added to a stream")
end
end
return
end
function close!(bbstream::BeagleBoneStream)
cmds = Tuple[]
for dev in stream.devices
close!(dev)
end
close!(bbstream.stream)
return
end
###### Defaults for Device
#What to do when connecting
initialize(::Device) = nothing
#What to do when disconnecting
close!(::Device) = nothing
#Which stream is the Device connected to
getstream(dev::Device) = dev.stream
#Set the stream the Device is connected to
setstream!(dev::Device, stream::LabStream) = dev.stream = stream
function safe_getwritecommand(dev::Device, val)
stream = try getstream(dev) catch
error("Device $dev not connected to a stream")
end
cmd = try getwritecommand(stream, dev, val) catch
error("Device $dev with output val $val not supported on stream $stream")
end
return cmd, stream
end
function safe_getreadcommand(dev::Device)
stream = try getstream(dev) catch
error("Device $dev not connected to a stream")
end
cmd = try getreadcommand(stream, dev) catch
error("Device $dev not supported to read from on stream $stream")
end
return cmd, stream
end
#Maybe rethink a bit to support IObox
function send!(dev::Device, val)
cmd, stream = safe_getwritecommand(dev, val)
serialize(stream, (true, 1, cmd))
return
end
function read(dev::Device)
cmd, stream = safe_getreadcommand(dev)
serialize(stream, (false, 1, cmd))
#TODO get, wait for and return response
return
end
mutable struct SysLED <: Device
i::Int32
nextout::Bool
latestread::Bool
stream::LabStream
SysLED(i::Int32) = new(i)
end
SysLED(i::Int64) = SysLED(convert(Int32, i), false, false)
#Save value to send later
set!(led::SysLED, val::Bool) = led.nextout = val
#Get the value from set! back for use
getsetvalue(led::SysLED) = led.nextout
#Get value that was read erlier
get(led::SysLED) = led.latestread
#No definition for IOBox since there are no LEDs
#Stream specific methods
function getwritecommand(stream::BeagleBoneStream, led::SysLED, val::Bool)
led.i [1,2,3,4] && error("SysLED $i not defined on BeagleBoneStream")
return ("sysled", led.i, val)
end
function getreadcommand(stream::BeagleBoneStream, led::SysLED)
led.i [1,2,3,4] && error("SysLED $i not defined on BeagleBoneStream")
return ("sysled", led.i)
end
include("server.jl")
stream = BeagleBoneStream(ip"127.0.0.1")
led2 = SysLED(2)
led3 = SysLED(3)
# Send info to steam about which inputs/otputs to initialize
# and adds a ref in motor and led to stream
init_devices!(stream, led2, led3)
ledon = true
for i = 1:10
set!(led2, ledon)
set!(led3, !ledon)
send!(stream) #Sends all the outputs to the stream in one atomic call
#read(stream) #Sends request to read, reads all inputs
sleep(1)
led_on = !led_on
end
for i = 1:10
send!(led2, ledon)
sleep(0.5)
send!(led3, !ledon)
#read(stream) #Sends request to read, reads all inputs
sleep(0.5)
led_on = !led_on
end
set!(led2, false)
set!(led3, false)
send!(stream)
close!(stream) #Tells BeagleBone to stop listening and close outputs
abstract type LabStream end
abstract type Device end
include("Device.jl")
##### General interface for devices
## A device to type T<:Device should define the methods
# set!(dev::T, val) # Remember val for next send!(::LabStream) command
# getsetvalue(dev::T) # Get the value that was saved to send
# get(dev::T) # Get val from last next read(::LabStream) command
# getwritecommand(stream::LabStream, dev::T, val) #Get canonlical representation of send command
# getreadcommand(stream::LabStream, dev::T) #Get canonlical representation of read command
## Default methods:
# initialize(::Device) = nothing #What to do when initializing
# close!(::Device) = nothing #What to do when disconnecting
# getstream(dev::Device) = dev.stream #Which stream is the Device connected to
# setstream!(dev::Device, stream::LabStream) = dev.stream = stream #Set the stream the Device is connected to
##### END General interface for devices
#Include the device definitions
include("SysLED.jl")
##### General interface for LabStream
## A stream of type T <: LabStream should define the methods
# serialize(::T, cmd) # Send data `cmd`
# init_devices!(::T, devs::Device...) # Initialize devices and connect them to stream
# send!(::T) # Send set! commands for all devices to stream, using getwritecommand(stream::LabStream, dev::Device, getsetvalue(dev::Device))
# read(::T) # Send read commands for all devices to stream, sing get(dev::Device)
# init_devices! # Initialize all connected devises, using initialize(::Device)
# close! # Close connection, call close!(::Device) on all connected devices
#Include the stream definitions
include("BeagleBoneStream.jl")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment