论如何优雅的进行Python与Lua交互,当然方法有多种,但很多仅凭纯Script操作不是很爽,本文就通过网页形式实现,实际操作来讲,有个网页UI操作也会方便很多。
背景: 之前某IoT项目,Device端与Cloud/App端数据通讯Protocol包括Binary、Json格式,全部由lua进行解析(实际是binary与json格式之间相互转换,是由于某系列设备只能用binary),但Lua脚本出bug不好排查,特别是App/Cloud/Device三方联调中要核对一堆消息,有个符号错了都会导致解析失败
问题:我们作为Device端开发人员写的Lua脚本,需要部署到Cloud的Paas上,该类Device上下行的数据都要通过Lua进行Binary - Json互转,才能正确处理,因此Lua出了问题,App/Cloud team需要把消息发给我们本地执行lua后,再和App/Cloud 检查消息, 非常麻烦,当然我是懒人,这么麻烦的也忍不了。
解决:使用Django搭个Bin-Json消息转换网站,App/Cloud/Device三方通过网站对消息数据 执行lua解析转换,检查各方数据是否有误。
项目使用的lua脚本只能在linux环境执行, 所以也做不了exe,所以通过网页形式开放给各开发人员,是最快捷方便的。
• Json转Binary:(会自动识别消息类型进行转换)
• Binary转Json:
如果解析失败,Django的console里也可以看error log:
…
translate.py接收Bin-Json转换页面 输入框的待转换消息,写入到msgInput.txt,
然后通过调用subprocess 的check_output执行 luaParser.lua(消息解析脚本)进行转换,并将转换完成的消息写入 msgOutput.txt, 最后将转换后的结果传回页面显示。
# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.views.decorators import csrf
from django.shortcuts import redirect
#from translator import translator
import subprocess as ss
import sys
import traceback
msgInput_FileName = "msgInput.txt"
msgOutput_FileName = "msgOutput.txt"
def WritetoFile(FileName,Data):
#fileName= 'record.txt'
with open(FileName,'w') as record:
strr = ""
content = strr.join(Data)
record.write(content+'\n')
def ReadFile(FileName):
fileName = FileName
with open(fileName) as record:
lines = record.read().splitlines()
#print(lines)
return lines
# handle POST request data
def translate_post(request):
if not request.session.get('is_login', None):
return redirect('/login/')
ctx ={}
if request.POST:
#Get input from post
MsgInput = request.POST['q']
print('Input from WebPage is:'+MsgInput)
WritetoFile(msgInput_FileName, MsgInput)
message = '输入为空, 请检查填写的内容!'
#input check
if MsgInput.strip():
try:
luaPrint = ss.check_output(['lua luaParser.lua'],shell=True)
#print (luaPrint)
Msgoutput = ReadFile(msgOutput_FileName)
#print (Msgoutput)
except ss.CalledProcessError as exc:
print(exc.returncode)
print(exc.output)
#Error log
tblog = traceback.format_exc()
Msgoutput = 'Error in Lua:'+str(exc.output)
Msgoutput+= '.....................ErrorCode is:'+ str(exc.returncode)
Msgoutput+= '.....................ErrorLog is:'+ tblog
ctx['rlt'] = Msgoutput
ctx['msgInput'] = MsgInput
#return a dictionary
return render(request, "login/index.html", ctx)
else:
return render(request, "login/index.html", {'message': message})
return render(request, 'login/index.html', locals())
if __name__ == '__main__':
if(sys.argv[1:] == []):
print('Not input parameter , Use latest Data in msgInput.txt...')
else:
MsgInput = sys.argv[1]
WritetoFile(msgInput_FileName, MsgInput)
msgInput.txt和msgOutput.txt文件作为消息数据缓存:
luaParser.lua读取msgInput.txt判断输入消息是binary 还是json数据,然后调用相应的script进行转换,转换后的数据写入msgOutput.txt,供页面显示
--Howard Xue , 20190322
launch = require'decode_launch'
code = launch'xxxchinaxxx.lua'
msgInput_FileName = "msgInput.txt"
msgOutput_FileName = "msgOutput.txt"
-- File Operation
function readMsgfile(filename)
file = io.open(filename, "r")
MsgRead = file:read()
--print(MsgRead)
file:close()
end
function writeMsgfile(path, content)
mode = "w+"
local file = io.open(path, mode)
if file then
if file:write(content) == nil then return false end
io.close(file)
return true
else
return false
end
end
-- Main begin
isBin2Json = isMsgData_Binary(msgInput_FileName)
readMsgfile(msgInput_FileName)
if isBin2Json == true then
-- Hex to Json
print(" Bin --> Json :")
outputData = code.convertFromDevice(code.hex(MsgRead))
writeMsgfile(msgOutput_FileName, outputData)
print(outputData)
else
--Json to Hex
print(" Json --> Bin :")
--print(code.hexDump(code.convertToDevice(MsgRead)))
outputData = code.hexDump(code.convertToDevice(MsgRead))
writeMsgfile(msgOutput_FileName, outputData)
print(outputData)
end
--readMsgfile(msgOutput_FileName)
--print(MsgRead)
-- Hex to Json
--print("Msg Output is:")
--print(code.convertFromDevice(code.hex(MsgRead)))
login/index.html,在输入框内输入待转换的数据后,点击一键转换,submit数据到translate.py, 并将转换后的结果(rlt 即msgOutput)显示出来。
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<link href="{% static 'login/css/login.css' %}" rel="stylesheet" />
<title>Bin-Json转换</title>
</head>
<body>
<br><br />
<div class="container">
<h1 style="color:#FFFFF0">{{ request.session.user_name }}! 欢迎回来! </h1>
<p>
<a style="color:#F08080" href="/logout/">退出登录</a>
</p>
<br> <br />
<div class="col">
<form action="/translate/" method="post">
{% csrf_token %}
{% if message %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
<input type="text" name="q" style="width:800px;height:50px;font-size:15px" placeholder="输入二进制或json消息" autofocus >
<!-- <input type="submit" value="Submit"> -->
<button type="submit" class="btn btn-primary">一键转换</button>
</form>
<div style="color:#FFFF00;word-break:break-all">注: 如果转换结果为Error, 请检查输入数据正确性,以及脚本是否报错</div>
</div>
<div style="font-family:verdana;padding:20px;border-radius:10px;border:5px solid #EE872A;">
<h3>Result:</h3>
<div style="color:#000000;word-break:break-all">{{ rlt }}</div>
</div>
<br><br/>
<div style="font-family:verdana;padding:20px;border-radius:10px;border:5px solid #EE872A;">
<h3>Input:</h3>
<div style="color:#000000;word-break:break-all">{{ msgInput }}</div>
</div>
</div> <!-- /container -->
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>
添加translate URL对应关系
from django.contrib import admin
from django.conf.urls import url
from django.urls import path
from django.urls import include
from login import views, translate
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
path('login/', views.login),
path('register/', views.register),
path('logout/', views.logout),
path('confirm/', views.user_confirm),
path('captcha/', include('captcha.urls')),
path('translate/', translate.translate_post),
]
Python实现自动发送邮件 --自动抓取博客/网站中留言的邮箱并发送相应邮件
Python自动生成代码 - 通过tkinter图形化操作并生成代码框架
Python解析CSV数据 - 通过Pandas解析逻辑分析仪导出的CSV数据
Python通过Django搭建网站执行Lua脚本 (实现数据解析)