tGeek tGeek - 1 year ago 90
jQuery Question

Phoenix Channel sending messages from a client outside the project

I wanted to send a message to my user channel of my Phoenix Application. I have joined a user_token with the channel as

in the
. I was successful doing it from another controller called the
by calling a broadcast method. The broadcast method is in the user channel. And I have written a jQuery file to handle the events. I was looking for something which can send messages to the same channel from outside of the project, because I wanted to do some IoT stuff. I have tried a python module called
and the JS client of Phoenix that it uses internally. Then, I found a disconnection always. I can't figure out the exact address of the websocket connection from Phoenix. If I am trying it with that Phoenix npm library in that project folder itself, it says
ReferenceError: window is not defined
always. And, I think it is because of the initialization part of the socket in the
file where it's written as

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

, but I am not sure. The thing that I have tried is below

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

In the python client, I was also trying to connect to this address and got a disconnection error. I want to do it for IoT purposes, where I want to monitor sensor data of a user. Each user will be having their own sensors to be monitored. So, I have configured the channel
channel as
. I need to send messages from my raspberry pi to this channel using those unique tokens of the users. My user_channel, user.js, app.js and socket.js are given below.

import {Socket} from "phoenix"

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


export default socket


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

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}
{:error, %{reason: "unauthorized"}}

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

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

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

defp authorized?(_payload) do

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


import socket from "./socket"

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

if (ul.length) {
var token ="id")
var topic = "users:" + token

// Join the topic
let channel =, {})
.receive("ok", data => {
console.log("Joined topic", topic)
.receive("error", resp => {
console.log("Unable to join topic", topic)
channel.on("change", toy => {
console.log("Change:", toy);

Answer Source

Finally, I am able to send and receive messages asynchronously from a python program. It uses websockets asyncio module from python. I figured out the various events required for phoenix channels like 'phx_join' for joining a topic and all. So, the following program worked.

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)

import RPi.GPIO as gpio

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


        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

            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.


Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download