-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhardware.lua
More file actions
188 lines (172 loc) · 8.08 KB
/
hardware.lua
File metadata and controls
188 lines (172 loc) · 8.08 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
local expect = require "expect"
local util = require "util"
--- The hardware module implements functions for operating on peripherals and
--- other hardware devices.
---
--- !doctype module
--- @class system.hardware
local hardware = {}
--- Wraps a device into an indexable object, allowing accessing properties and
--- methods of the device by indexing the table.
---
--- If an object is passed, this simply re-wraps the device in a new object.
--- @param device string The device specifier or object to wrap
--- @return device result The wrapped device
--- @usage Wrap a device, use a property, and call a method:
--- ```lua
--- local computer = hardware.wrap("/")
--- print(computer.isOn)
--- computer.label = "My Computer"
--- computer:reboot()
--- ```
function hardware.wrap(device)
expect(1, device, "string", "device", "devicetree")
if type(device) ~= "string" then device = getmetatable(device).uuid end
local info = util.syscall.devinfo(device)
if not info then return nil end
local methods, properties = util.syscall.devmethods(device), util.syscall.devproperties(device)
for _, v in ipairs(properties) do properties[v] = true end
local retval = {}
for _, v in ipairs(methods) do retval[v] = function(self, ...) return util.syscall.devcall(device, v, ...) end end
return setmetatable(retval, {
__name = "device",
uuid = info.uuid,
__index = function(self, idx)
if type(idx) == "string" and properties[idx] then return util.syscall.devcall(device, "get" .. idx:gsub("^.", string.upper)) end
end,
__newindex = function(self, idx, val)
if type(idx) == "string" and properties[idx] and self["set" .. idx:gsub("^.", string.upper)] then return util.syscall.devcall(device, "set" .. idx:gsub("^.", string.upper), val) end
end,
__tostring = function(self)
return "wrapped device: " .. (info.displayName or info.uuid)
end
})
end
--- Returns a list of wrapped devices that implement the specified type.
--- @param type string The type to search for
--- @return device ... The devices found, or `nil` if none were found
--- @see hardware.wrap For wrapping a single device by path
function hardware.find(type)
expect(1, type, "string")
local retval = {}
for i, v in ipairs{util.syscall.devfind(type)} do retval[i] = hardware.wrap(v) end
return table.unpack(retval)
end
--- Returns a list of device paths that match the device specifier or object.
---
--- If an absolute path is specified, this returns the same path back.
--- If a device object is specified, this returns the path to the device.
--- @param device string|device The device specifier or object to read
--- @return string ... The paths that match the specifier or device object.
function hardware.path(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devlookup(device)
else return util.syscall.devlookup(getmetatable(device).uuid) end
end
--- Returns whether the device implements the specified type.
--- @param device string|device The device specifier or object to query
--- @param type string The type to check for
--- @return boolean result Whether the device implements the type
function hardware.hasType(device, typ)
expect(1, device, "string", "device", "devicetree")
expect(2, typ, "string")
local info
if type(device) == "string" then info = util.syscall.devinfo(device)
else info = util.syscall.devinfo(getmetatable(device).uuid) end
if not info then error("No such device", 2) end
return info.types[typ] ~= nil
end
--- Returns a table of information about the specified device.
--- @param device string|device The device specifier or object to query
--- @return HWInfo|nil result The hardware info table, or `nil` if no device was found
function hardware.info(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devinfo(device)
else return util.syscall.devinfo(getmetatable(device).uuid) end
end
--- Returns a list of methods implemented by this device.
--- @param device string|device The device specifier or object to query
--- @return string[] result The methods available to call on this device
function hardware.methods(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devmethods(device)
else return util.syscall.devmethods(getmetatable(device).uuid) end
end
--- Returns a list of properties implemented by this device.
--- @param device string|device The device specifier or object to query
--- @return string[] result The properties available on this device
function hardware.properties(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devproperties(device)
else return util.syscall.devproperties(getmetatable(device).uuid) end
end
--- Returns a list of children of this device.
--- @param device string|device The device specifier or object to query
--- @return string[] result The names of children of the device
function hardware.children(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devchildren(device)
else return util.syscall.devchildren(getmetatable(device).uuid) end
end
--- Calls a method on a device.
--- @param device string|device The device specifier or object to call on
--- @param method string The method to call
--- @param ... any Any arguments to pass to the method
--- @return any ... The return values from the method
function hardware.call(device, method, ...)
expect(1, device, "string", "device", "devicetree")
expect(2, method, "string")
if type(device) == "string" then return util.syscall.devcall(device, method, ...)
else return util.syscall.devcall(getmetatable(device).uuid, method, ...) end
end
--- Toggles whether this process should receive events from the device.
--- @param device string|device The device specifier or object to modify
--- @param state? boolean Whether to allow events (defaults to true)
function hardware.listen(device, state)
expect(1, device, "string", "device", "devicetree")
expect(2, state, "boolean", "nil")
if type(device) == "string" then return util.syscall.devlisten(device, state)
else return util.syscall.devlisten(getmetatable(device).uuid, state) end
end
--- Locks the device from being called on or listened to by other processes.
--- @param device string|device The device specifier or object to modify
--- @param wait? boolean Whether to wait for the device to unlock if (defaults to true)
--- it's currently locked by another process
--- @return boolean result Whether the current process now owns the lock
--- @see unlock To unlock the device afterward
function hardware.lock(device, wait)
expect(1, device, "string", "device", "devicetree")
expect(2, wait, "boolean", "nil")
if type(device) == "string" then return util.syscall.devlock(device, wait)
else return util.syscall.devlock(getmetatable(device).uuid, wait) end
end
--- Unlocks the device after previously locking it.
--- @param device string|device The device specifier or object to modify
--- @see lock To lock the device
function hardware.unlock(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devunlock(device)
else return util.syscall.devunlock(getmetatable(device).uuid) end
end
local function makeTree(path)
local info = hardware.info(path or "/")
if not info then return nil end
path = path or ""
return setmetatable({}, {
__name = "devicetree",
uuid = info.uuid,
__index = function(self, idx)
return makeTree(path .. "/" .. idx)
end,
__newindex = function() end
})
end
--- A table that allows accessing device object pointers in a tree. This is
--- simply syntax sugar for real paths.
--- @usage To access the left redstone signal
--- ```lua
--- local device = hardware.wrap(hardware.tree.redstone.left)
--- print(device.input)
--- ```
hardware.tree = makeTree()
return hardware