我使用Raspberry Pi收集传感器数据并设置数字输出,以便其他应用程序使用套接字服务器轻松设置和获取值。 但是我遇到了一些问题,找到一种优雅的方法,可以在套接字服务器上提供所有数据,而无需为每种数据类型编写函数。
我希望在套接字服务器上提供的值和方法的一些示例:
do[2].set_low() # set digital output 2 low
do[2].value=0 # set digital output 2 low
do[2].toggle() # toggle digital output 2
di[0].value # read value for digital input 0
ai[0].value # read value for analog input 0
ai[0].average # get the average calculated value for analog input 0
ao[4].value=255 # set analog output 4 to byte value 255
ao[4].percent=100 # set analog output 4 to 100%
我已尝试eval()
和exec()
:
self.request.sendall(str.encode(str(eval('item.' + recv_string)) + '\n'))
除非我使用等号(eval()
),否则 =
有效,但由于涉及危险,我不会对解决方案感到满意。 exec()
完成工作,但不会返回任何价值,也很危险。
我还试过getattr()
:
recv_string = bytes.decode(self.data).lower().split(';')
values = getattr(item, recv_string[0])
self.request.sendall(str.encode(str(values[int(recv_string[1])].value) + '\n'))
^^^^^
这适用于获取我的属性,上面的示例适用于获取value
所获得的属性的getattr()
。但我也无法弄清楚如何在getattr()
属性上使用value
。
分号(;
)用于分割传入的命令,我尝试了多种格式化命令的方法:
# unit means that I want to talk to a I/O interface module,
# and the name specified which one
unit;unit_name;get;do;1
unit;unit_name;get;do[1]
unit;unit_name;do[1].value
我可以自由选择格式,因为我也在编写使用这些命令的软件。我还没有找到满足我所有需求的好格式。
有什么建议我如何写出一种优雅的方式来访问和返回上面的数据?每次将新的值类型或方法添加到I / O端口时,最好不得不向套接字服务器添加新方法。
修改:这不是公开的,只能在我的网络上使用。
答案 0 :(得分:1)
为您的API制作所有方法,以便始终可以使用eval:
def value_m(self, newValue=None):
if newValue is not None:
self.value = newValue
return self.value
然后你可以随时
result = str(eval(message))
self.request.sendall(str.encode(result + '\n'))
对于您的message
,我建议将消息格式化为完全包含命令的确切语法,以便按原样eval
编辑,例如
message = 'do[1].value_m()' # read a value, alternatively...
message = 'do[1].value_m(None)'
或写
message = 'do[1].value_m(0)' # write a value
这样可以很容易地使您的消息与API保持同步,因为它们必须完全匹配,您将无法处理第二个DSL。你真的不想在你的IO之上维护第二个API。
这是一个非常简单的方案,适用于家庭项目。我会在评估中建议一些错误处理,如下所示:
import traceback
try:
result = str(eval(message))
except Exception:
result = traceback.format_exc()
self.request.sendall(str.encode(result + '\n'))
这样,您的调用者将在返回的消息中收到异常回溯的打印输出。这将使调试不良呼叫变得更加容易。
注意如果这是面向公众的,则无法执行此操作。必须清理所有输入。您将必须解析每条指令并将其与可用(和期望)命令列表进行比较,并验证所有内容的输入有效性和有效性范围。对于这种情况,您最好只使用一个用于Web服务的输入验证系统,这个问题会得到很多关注。