MagicMirror² v2.12.0 is available! For more information about this release, check out this topic.

Running Python under node.js



  • Hi,

    A few weeks ago I started looking into getting notifications onto the mirror from python. Whilst it was relatively straight forward to run python within a shell from the node-helper, I ran into various problems with user privileges and environments.

    To get around this I had a play with rabbitmq. Using amqp for the node end and pika for the python. This opens up a whole world of possibilities for my mirror without having to learn javascript (above the basics & plagiarising code snippets from the built in modules) .

    node-helper end looks like. Sorry it’s a bit messy & I went overboard on the error capture.

    var amqp = require("amqplib/callback_api");
    
    PStart: function starter() {
    const self = this;
      amqp.connect("amqp://localhost", function(err, conn) {
        if (err) {
          console.error("[AMQP]", err.message);
          return setTimeout(starter, 1000);
        }
        conn.on("error", function(err) {
          if (err.message !== "Connection closing") {
            console.error("[AMQP] conn error", err.message);
          }
        });
        conn.on("close", function() {
          console.error("[AMQP] reconnecting");
          return setTimeout(starter, 1000);
        });
        console.log("[AMQP] connected");
        amqpConn = conn;
    
      amqpConn.createChannel(function(err, ch) {
        if (closeOnErr(err)) return;
        ch.on("error", function(err) {
          console.error("[AMQP] channel error", err.message);
        });
        ch.on("close", function() {
          console.log("[AMQP] channel closed");
        });
    
        ch.prefetch(10);
        ch.assertQueue("message", { durable: false }, function(err, _ok) {
          if (closeOnErr(err)) return;
          ch.consume("message", function(msg) {
    try {
     var fp = JSON.parse(msg.content.toString());
        ch.ack(msg);
        } catch (e) {
          closeOnErr(e);
        }
                    if (fp[0].data == "data"){
                    self.sendData({"PlrStat": fp[0].PlrStat, "TrkNxt":fp[0].TrkNext, "Station": fp[0].Station, "Said": fp[0].Said);
                    } else if (fp[0] == "status") {
                    console.log("[MMM-Radio]" + fp[0].status);
                    } else {
                    console.log("Got something");
                    console.log(msg);
                    console.log(fp[0].data);}
    })}, { noAck: false });
          console.log("Worked");
          });
    });
    }  });
    
    function closeOnErr(err) {
      if (!err) return false;
      console.error("[AMQP] error", err);
      amqpConn.close();
      this.Pstart();
      return true;
    }
    
    

    Python end:

    import pika
    
    def to_node(message):
        try:
            channel.basic_publish(exchange='',
                                  routing_key='message',
                                  body=json.dumps(message))
        except Exception:
            connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
            channel = connection.channel()
            channel.queue_declare(queue='message')
            channel.basic_publish(exchange='',
                                  routing_key='message',
                                  body=json.dumps(message))
    
    

    The bit in the exception is the initial setup for the connection, it does occasionally time out so re-establish if the publishing doesn’t work.

    Some useful tutorials on rabbitmq can be found here

    Hope this is a help to some of you who know very little about js & do all the complicated stuff with other languages.



  • @grantc66 cool, thanks…

    for node, you could have spun off a long running python app,
    and added data.on() event handlers in javascript node_helper to get called each time the python app wrote to the console (stdout)… which could have been json data, or whatever text you liked

    const {spawn} = require('child_process')
    
    const child = spawn('pwd');
    
    child.stdout.on('data', (data) => {
      console.log(`child stdout:\n${data}`);
    });
    
    child.stderr.on('data', (data) => {
      console.error(`child stderr:\n${data}`);
    });
    


  • Node js is one of the powerful tools of programming and using this if you are working on python it help you a lot. printer offline fix helped me to know more about python.


Log in to reply