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)