1

Ich wollte eine Nachricht an meinen Benutzerkanal meiner Phoenix-Anwendung senden. Ich habe ein user_token mit dem Kanal als users:user_token in der user_channel.ex verbunden. Ich habe es erfolgreich von einem anderen Controller namens toy_controller getan, indem ich eine Broadcast-Methode aufgerufen habe. Die Broadcast-Methode befindet sich im Benutzerkanal. Und ich habe eine jQuery-Datei geschrieben, um die Ereignisse zu behandeln. Ich suchte nach etwas, das Nachrichten von außerhalb des Projekts an denselben Kanal senden kann, weil ich etwas IoT-Zeug machen wollte. Ich habe versucht, ein Python-Modul namens occamy.socket und den JS-Client von Phoenix, die es intern verwendet. Dann habe ich immer eine Trennung gefunden. Ich kann die genaue Adresse der Websocket-Verbindung von Phoenix nicht herausfinden. Wenn ich es mit dieser Phoenix npm-Bibliothek in diesem Projektordner selbst versuche, heißt es immer ReferenceError: window is not defined. Und ich glaube, es ist wegen der Initialisierung Teil der Buchse in der web/static/js/socket.js Datei ist, wo es alsPhoenix Channel sendet Nachrichten von einem Client außerhalb des Projekts

let socket = new Socket("/socket", {params: {token: window.userToken}})        

geschrieben, aber ich bin nicht sicher. Die Sache, die ich versucht habe, ist unter

var Socket = require("phoenix-socket").Socket; 
var socket = new Socket("ws://localhost:4000/socket"); 

Im Python-Client, wurde ich auch an diese Adresse zu verbinden versucht und bekam einen Trennungsfehler. Ich möchte es für IoT-Zwecke tun, wo ich Sensordaten eines Benutzers überwachen möchte. Jeder Benutzer muss seine eigenen Sensoren überwachen lassen. Also, ich habe den Kanal topic:subtopic Kanal als users:user_token konfiguriert. Ich muss Nachrichten von meinem raspberry pi an diesen Kanal senden, indem ich diese einzigartigen Token der Nutzer benutze. Mein user_channel, user.js, app.js und socket.js sind unten angegeben.

//web/static/js/socket.js 
 
import {Socket} from "phoenix" 
 

 
let socket = new Socket("/socket", {params: {token: window.userToken}}) 
 

 

 
socket.connect() 
 

 

 
export default socket

//web/static/app.js 
 

 

 
import "phoenix_html" 
 
import user from "./user"

#web/channels/user_channel.ex 
defmodule Tworit.UserChannel do 
    use Tworit.Web, :channel 

    def join("users:" <> user_token, payload, socket) do 
     if authorized?(payload) do 
      {:ok, "Joined To User:#{user_token}", socket} 
     else 
      {:error, %{reason: "unauthorized"}} 
     end 
    end 


    def handle_in("ping", payload, socket) do 
     {:reply, {:ok, payload}, socket} 
    end 


    def handle_in("shout", payload, socket) do 
     broadcast socket, "shout", payload 
     {:noreply, socket} 
    end 


    def handle_out(event, payload, socket) do 
     push socket, event, payload 
     {:noreply, socket} 
    end 


    defp authorized?(_payload) do 
     true 
    end 

    def broadcast_change(toy, current_user) do 
     payload = %{ 
     "name" => toy.name, 
     "body" => toy.body 
     } 
     Tworit.Endpoint.broadcast("users:#{current_user.token}", "change", payload) 
    end 

end 

//web/static/js/user.js 
 
import socket from "./socket" 
 

 
$(function() { 
 
    let ul = $("ul#em") 
 

 
    if (ul.length) { 
 
    var token = ul.data("id") 
 
    var topic = "users:" + token 
 
\t \t 
 
    // Join the topic 
 
    let channel = socket.channel(topic, {}) 
 
    channel.join() 
 
     .receive("ok", data => { 
 
     console.log("Joined topic", topic) 
 
     }) 
 
     .receive("error", resp => { 
 
     console.log("Unable to join topic", topic) 
 
     }) 
 
    channel.on("change", toy => { 
 
\t  console.log("Change:", toy); 
 
\t  $("#message").append(toy["name"]) 
 
    }) 
 
    } 
 
});

Antwort

0

Endlich kann ich Nachrichten asynchron von einem Python-Programm senden und empfangen. Es verwendet websockets asyncio-Modul von Python. Ich fand die verschiedenen Ereignisse heraus, die für Phönix-Kanäle wie 'phx_join' erforderlich sind, um einem Thema beizutreten. Also, das folgende Programm hat funktioniert.

import asyncio 
import websockets 
import json 
import time 
from random import randint 
import serial 

from pyfirmata import Arduino, util 

board = Arduino('/dev/ttyACM1') 

it = util.Iterator(board) 
it.start() 
board.analog[0].enable_reporting() 
board.analog[1].enable_reporting() 
board.analog[2].enable_reporting() 
board.analog[3].enable_reporting() 

import RPi.GPIO as gpio 

gpio.setmode(gpio.BCM) 
gpio.setup(14, gpio.OUT) 


async def main(): 
    async with websockets.connect('ws://IP_addr:4000/socket/websocket') as websocket: 
     data = dict(topic="users:user_token", event="phx_join", payload={}, ref=None) 
     #this method joins the phoenix channel 
     await websocket.send(json.dumps(data)) 

     print("Joined") 

     while True: 
      msg = await retrieve() # waits for data from arduino analog pins 
      await websocket.send(json.dumps(msg)) # sends the sensor output to phoenix channel 

      print("sent") 
      call = await websocket.recv() # waits for anything from the phoenix server 
      control = json.loads(call) 

      # I have sent values from 2 buttons for swicthing a led with event 'control' 

      if(control['event'] == "control"): 
       event(control['payload']['val']) #swiches the led as per the input from event 'control' 


      print("< {}".format(call)) 

def event(val): 
    if(val == "on"): 
     gpio.output(14, True) 
    if(val == "off"): 
     gpio.output(14, False) 

async def retrieve(): 
    #analog read 
    load = board.analog[0].read() 
    pf = board.analog[1].read() 
    reading = board.analog[2].read() 
    thd = board.analog[3].read() 
    output = {"load": load, "pf": pf, "reading": reading,"thd": thd} 

    msg = dict(topic="users:user_token", event="sensor_output", payload=output, ref=None) # with 
    #event "sensor_outputs" 
    #the phoenix server displays the data on to a page. 

    print(msg) 
    return(msg) 

asyncio.get_event_loop().run_until_complete(main()) 
asyncio.get_event_loop().run_forever()