github.com/stampzilla/stampzilla-go@v2.0.0-rc9+incompatible/nodes/stampzilla-magicmirror/web/src/components/Websocket.js (about) 1 import { Component } from 'react' 2 import { connect } from 'react-redux' 3 import ReconnectableWebSocket from 'reconnectingwebsocket' 4 import Url from 'url' 5 6 import { connected, disconnected } from '../ducks/connection' 7 import { subscribe as devices } from '../ducks/devices' 8 import { update as config } from '../ducks/config' 9 10 // Placeholder until we have the write func from the websocket 11 let writeSocket = null 12 const writeFunc = data => { 13 if (writeSocket === null) { 14 throw new Error('Not initialized yet') 15 } 16 writeSocket.send(data) 17 } 18 export const write = msg => writeFunc(JSON.stringify(msg)) 19 20 class Websocket extends Component { 21 constructor(props) { 22 super(props) 23 24 this.subscriptions = {} 25 } 26 27 componentDidMount() { 28 this.setupSocket(this.props) 29 } 30 31 componentWillReceiveProps(props) { 32 this.setupSocket(props) 33 } 34 35 componentWillUnmount() { 36 if (typeof this.socket !== 'undefined') { 37 this.socket.close() 38 } 39 } 40 41 onOpen = () => () => { 42 this.props.dispatch(connected()) 43 44 const url = Url.parse(this.props.url) 45 46 this.subscribe({ 47 devices 48 }) 49 } 50 onClose = () => () => { 51 this.props.dispatch(disconnected()) 52 this.subscriptions = {} 53 } 54 onMessage = () => event => { 55 const { dispatch } = this.props 56 const parsed = JSON.parse(event.data) 57 58 const subscriptions = this.subscriptions[parsed.type] 59 if (subscriptions) { 60 subscriptions.forEach(callback => callback(parsed.data)) 61 } 62 switch (parsed.type) { 63 case 'config': { 64 dispatch(config(parsed.data)) 65 break 66 } 67 default: { 68 // Nothing 69 } 70 } 71 } 72 73 setupSocket(props) { 74 console.log(props) 75 const { url } = props 76 if (this.socket) { 77 // this is becuase there is a bug in reconnecting websocket causing it to retry forever 78 this.socket.onclose = () => { 79 throw new Error('force close socket') 80 } 81 // Close the existing connection 82 this.socket.close() 83 } 84 85 this.socket = new ReconnectableWebSocket(url, undefined, { 86 reconnectInterval: 3000, 87 timeoutInterval: 1000 88 }) 89 writeSocket = this.socket 90 // writeFunc = this.socket.send; 91 this.socket.onmessage = this.onMessage() 92 this.socket.onopen = this.onOpen() 93 this.socket.onerror = this.onClose() 94 this.socket.onclose = this.onClose() 95 } 96 97 subscribe = ducks => { 98 const subscriptions = [] 99 Object.keys(ducks).forEach(duck => { 100 if (!ducks[duck]) { 101 return 102 } 103 104 const channels = ducks[duck](this.props.dispatch) 105 Object.keys(channels).forEach(channel => { 106 this.subscriptions[channel] = this.subscriptions[channel] || [] 107 this.subscriptions[channel].push(channels[channel]) 108 subscriptions.push(channel) 109 }) 110 }) 111 112 write({ 113 type: 'subscribe', 114 body: subscriptions 115 }) 116 } 117 118 render = () => null 119 } 120 121 const mapToProps = state => ({}) 122 export default connect(mapToProps)(Websocket)