-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtossam.lua
156 lines (141 loc) · 3.44 KB
/
tossam.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
--
-- TOSSAM
-- author: Bruno Silvestre
-- e-mail: [email protected]
--
local codec = require("tossam.codec")
local hdlc = require("tossam.hdlc")
local am = require("tossam.am")
local serial = require("tossam.serial")
local sf = require("tossam.sf")
local net = require("tossam.network")
--------------------------------------------------------------------------------
local strheader = [[
nx_struct header[0] {
nx_uint8_t am;
nx_uint16_t dst;
nx_uint16_t src;
nx_uint8_t len;
nx_uint8_t grp;
nx_uint8_t type;
};
]]
local defheader = (codec.parser(strheader))[1]
local function register(conn, str)
local defs, err = codec.parser(str)
if err then return false, err end
local tmp = {}
for i, def in ipairs(defs) do
if conn.defs[def.id] or tmp[def.id] then
return false, "AM type already defined: " .. def.name
else
tmp[def.id] = true
end
end
for i, def in ipairs(defs) do
conn.defs[def.id] = def
conn.defs[def.name] = def
end
return true
end
local function registered(conn)
local defs = {}
for k, v in pairs(conn.defs) do
if type(k) == "string" then
defs[k] = v.id
end
end
return defs
end
local function unregister(conn, id)
local def = conn.defs[id]
if def then
conn.defs[def.id] = nil
conn.defs[def.name] = nil
return true
end
return false
end
local function close(conn)
return conn.back:close()
end
local function receive(conn)
local pck, err = conn.back:receive()
if not pck then return nil, err end
local head = codec.decode(defheader, pck, 1)
local def = conn.defs[head.type]
if not def then
return nil, "Unknown AM type"
end
-- skip the header
local payload = codec.decode(def, pck, 9)
payload[1] = def.id
payload[2] = def.name
return payload
end
local function send(conn, payload, def)
def = def or payload[1]
if (type(def) ~= "number" and type(def) ~= "string") then
return false, "Invalid parameters"
end
def = conn.defs[def]
if not def then
return false, "Unknown AM type"
end
payload = codec.encode(def, payload)
local head = {
am = 0,
dst = 0,
src = 0,
len = #payload,
grp = 0,
type = def.id,
}
head = codec.encode(defheader, head)
return conn.back:send(head..payload)
end
local function settimeout(conn, v)
conn.back:settimeout(v)
end
local function backend(conn)
return conn.back:backend()
end
local meta = { }
meta.__index = {
backend = backend,
close = close,
receive = receive,
register = register,
registered = registered,
send = send,
settimeout = settimeout,
unregister = unregister,
}
local function connect(conf)
local back, err
if conf.protocol == "serial" then
back, err = serial.open(conf.port, conf.baud)
elseif conf.protocol == "sf" then
back, err = sf.open(conf.host, conf.port)
elseif conf.protocol == "network" then
back, err = net.open(conf.host, conf.port)
elseif conf.protocol == "external" then
back = conf.backend
else
return nil, "invalid protocol"
end
if not back then
return nil, err
end
if conf.protocol == "serial" or conf.protocol == "network" or conf.am then
back = am.wrap(hdlc.wrap(back))
end
local conn = {
defs = {},
back = back,
}
return setmetatable(conn, meta)
end
--------------------------------------------------------------------------------
-- Module
return { connect = connect }