发生数据库更改时,是否可以将消息发送到MQTT mosquitto代理?

时间:2019-02-19 09:49:50

标签: python django mqtt paho

我正在一个项目上,该项目最终将是一个显示设备数据并可以控制这些设备的网站。我目前正在使用Paho MQTT Python库在python中编写代码。我成功地通过mosquitto代理成功发送和接收了加密的消息。我创建了一个客户端,它是一种监视客户端,它订阅了通配符主题,以便接收通过代理传递的所有消息,并最终将它们存储到数据库中。我正在使用Django 2.1.5,mosquitto broker 1.5,在python中工作。

我现在面临的问题是,一旦数据库发生更改,我就无法找到一种将消息发送到mosquitto代理的方法。假设我有一个网站,其中显示了所有已连接的设备,并且我想将其关闭,然后单击一个按钮,这将更改数据库表,然后必须向代理发送一条消息,以通知该设备应关掉。我知道我可以将网站设置为客户端,然后在Websocket上使用MQTT,但这不是理想的选择。

我尝试了django信号,这似乎工作正常。问题在于django信号触发的函数会创建新的mqtt客户端的新实例。我希望已经运行的监视客户端发送消息,即触发其定义的功能之一,该功能将在发送信号时立即发送消息。

class Post(models.Model):
    title = models.CharField(max_length=50)
    def __str__(self):
        return self.title

def save_post(sender, instance, **kwargs):
    message = {
        "client_id": "abc",
        "message": "Created new model: " + str(instance),
    }
     publish.single("house/StateServer/receive", 
         payload=json.dumps(message), 
         port=8081, hostname="localhost", retain=False, 
         auth = {'username':"abc", 'password':"abc"}, 
         client_id="abc",tls = {"ca_certs":"","certfile":"","keyfile":"",})


post_save.connect(save_post, sender=Post)

我希望“ save_post”函数触发运行于24/7并存储在另一个文件(例如“ monitor.py”)中的监视客户端的功能。监视客户端的此功能将接收所需的数据:消息的有效负载和终端设备的主题,并将其发送给mosquitto代理。

2 个答案:

答案 0 :(得分:0)

我最近不得不通过Django post_save做类似的事情。就我而言,作为不同进程运行的等效“不同文件monitor.py”将启动运行简单SimpleHTTPServer的线程,该线程完成所有发布工作。由于SimpleHTTPServer可以将接收到的要发布的数据添加到队列中,并让另一个线程处理POST处理程序,而POST处理程序立即返回,因此这也使您可以随意处理事务。

作为参考,此处提供有关json和simplehttpserver的信息:Reading JSON from SimpleHTTPServer Post data

答案 1 :(得分:0)

是的,您可以在var express = require('express'); var app = express(); var userRoute = require('./routes/users'); var postRoute = require('./routes/posts'); var bodyParser = require('body-parser'); var logger = require('morgan'); var models = require('./models'); var User = require('./models/user'); var session = require('express-session'); var cookieParser = require('cookie-parser') ; var cookieSession = require('cookie-session'); var dotenv = require('dotenv'); var env = dotenv.config(); var cors = require('cors'); const port = process.env.PORT || 8000; const passport = require('passport'); const path = require('path'); const allowOrigin = process.env.ALLOW_ORIGIN || '*' // CORS Middleware app.use(function (req, res, next) { // Website you wish to allow to connect res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8000'); // Request methods you wish to allow res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // Request headers you wish to allow res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // Set to true if you need the website to include cookies in the requests sent // to the API (e.g. in case you use sessions) res.setHeader('Access-Control-Allow-Credentials', true); // Pass to next layer of middleware next(); }); if (!process.env.PORT) { require('dotenv').config() } if (!process.env.PORT) { console.log('[api][port] 8000 set as default') console.log('[api][header] Access-Control-Allow-Origin: * set as default') } else { console.log('[api][node] Loaded ENV vars from .env file') console.log(`[api][port] ${process.env.PORT}`) console.log(`[api][header] Access-Control-Allow-Origin: ${process.env.ALLOW_ORIGIN}`) } app.use(cors({ origin: process.env.ALLOW_ORIGIN, credentials:false, allowedHeaders: 'X-Requested-With, Content-Type, Authorization, origin, X-Custom-Header', methods: 'GET, POST, PATCH, PUT, POST, DELETE, OPTIONS', })) app.use(logger('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use(cookieParser()); app.use(bodyParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended:false })); app.use(session({ secret : process.env.JWT_SECRET, resave: false, saveUninitialized:true, })); app.use(passport.initialize()); app.use(passport.session()); require('./config/passport')(passport); require('./config/passport-github')(passport); app.use('/api/users', userRoute ) app.use('/api/posts', postRoute ) app.use(function(req, res, next) { res.locals.user = req.user; // This is the important line console.log(res.locals.user); next(); }); app.listen(port, () => { console.log('[api][listen] http://localhost:' + port) }) 信号中进行操作。请参阅此answer。但我建议您在线程中进行操作,您可以保留post_save进行发送,但是如果您希望从接收方发回确认,则不能保证