1

我想發送一條消息給我的Phoenix應用程序的用戶頻道。我加入了user_channel.ex中的頻道爲users:user_token的user_token。我通過調用廣播方法從另一個名爲toy_controller的控制器成功完成。廣播方法在用戶頻道中。我寫了一個jQuery文件來處理事件。我一直在尋找可以從項目之外向同一頻道發送消息的東西,因爲我想做一些物聯網的東西。我已經嘗試了一個名爲occamy.socket的python模塊以及它在內部使用的Phoenix的JS客戶端。然後,我總是發現斷開連接。我無法弄清鳳凰網絡連接的確切地址。如果我正在使用該項目文件夾中的Phoenix npm庫,它總是說ReferenceError: window is not defined。而且,我認爲這是因爲在web/static/js/socket.js文件插座的初始化部分的地方它寫成菲尼克斯頻道發送來自項目外客戶的消息

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

,但我不知道。我試過的東西是

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

在python客戶端,我也試圖連接到這個地址,並得到了斷開連接錯誤。我想爲了IoT的目的而做它,我想監視用戶的傳感器數據。每個用戶都將擁有自己的傳感器進行監控。因此,我已將頻道topic:subtopic頻道配置爲users:user_token。我需要使用用戶的這些獨特的令牌從我的樹莓派發送消息到這個頻道。下面給出了我的user_channel,user.js,app.js和socket.js。

//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"]) 
 
    }) 
 
    } 
 
});

回答

0

最後,我能夠從python程序異步發送和接收消息。它使用python的websockets asyncio模塊。我想出了鳳凰頻道所需的各種事件,如「phx_join」,以加入主題和所有內容。所以,下面的程序工作。

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()