npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@mckennatim/mqtt-hooks

v2.0.2

Published

A custom package to add Context provider and hooks to react apps that connect to esp8266 and esp32 based sensor/relays/timers. Applications can use any subset of sensors, relays and timers from one or more devices. Talks to both mqtt broker and to server

Downloads

31

Readme

@mckenna.tim/react-mqtt

A custom package used by https://sitebuilt.net/qr/ to add Context provider and hooks to react apps that connect to esp8266 and esp32 based sensor/relays/timers. Applications can use any subset of sensors, relays and timers from one or more devices. Talks to both mqtt broker and to server providing application configuration and authentication.

Usage

npm install @mckennatim/react-hooks

import {ClientSocket, 
  Context, 
  useDevSpecs,  
  processMessage, 
  getZinfo,
  getDinfo, 
  setupSocket,
  monitorFocus
} from '@mckennatim/react-hooks'  

Typically an app (like the prototype app Cascada) that uses mqtt-hooks

  • imports ClientSocket in a top level component like <App/>
  • imports { connect, Context, useDevSpecs, processMessage, getZinfo,getDinfo ,setupSocket, monitorFocus} into the control component (like Control) that connects whenever it is loaded, gets all the static app and device data from the database, parses it, processes messages for dispatch to components down line and sets up publish ability.
  • imports {startWhen, endWhen, newInterval, add2sched, m2hm, m2ms} utlity functions for components that need to put things in the right format to publish to mqtt (like Pond and Spot)

During testing be sure to change between local and npm imports everywhere at once. In Cascada that is in App, Control, Pond and Spot (SchedMod(deprecated))

ClientSocket

ClientSocket is used to wrap any component+children that need client and/or publish objects. (The client is not connected at this point)

  <ClientSocket cfg={cfg}>
    <App />
  </ClientSocket>   

where cfg is of the form and connects you to the mqtt broker

{cfg.mqtt_server, cfg.mqtt_port, cfg.appid}

example

"appid": "greenhouse",
"mqtt_server": "services.sitebuilt.net/iotb/wss"
	"mqtt_port": 4333,

ClientSocket returns Context.Provider with client from a new Paho.Client and publish from a new Paho.Message

  <Context.Provider value={[this.client, this.publish]}>
    {this.props.children}
  </Context.Provider>    

Context

Context provides a way to access client and publish form the react builtin useContext hook

const [client, publish] = useContext(Context);

All it is is what you get back from react's builtin createContext

import { createContext } from "react";
export const Context = createContext();

useDevSpec

useDevSpec uses the useEffect hook to fetch [one time] information from the server about the devices and zones and binfo for the application at a particular address with a particular owner. This is set inside a token stored in local storage placed there by the authentication/authorization app https://iot.sitebuilt.net/v3/signin/

const {devs, zones, binfo}= useDevSpecs(ls, cfg, client, (client, devs)=>{
  setupSocket(client, devs, publish, topics, (devs, client)=>doOtherShit(devs, client))
})

dvs and zones binfo are in the form

devs

{
  "CYURD004": [
    {
      "sr": 0,
      "label": "temp_gh"
    },
    {
      "sr": 1,
      "label": "hum_gh"
    },
    {
      "sr": 2,
      "label": "light_gh"
    }
  ],
  "CYURD006": [
    {
      "sr": 0,
      "label": "temp_out"
    }
  ]
}

zones

[
    {
        "id": "temp_gh",
        "name": "Greenhouse Temperature",
        "img": "temp_gh.jpg"
    },
    {
        "id": "hum_gh",
        "name": "Greenhouse Humidity",
        "img": "hum_gh.jpg"
    },
    {
        "id": "light_gh",
        "name": "Greenhouse Lights",
        "img": "light_gh.jpg"
    },
    {
        "id": "temp_out",
        "name": "Outside Temperature",
        "img": "temp_out.jpg"
    }
]
binfo

{
    "auth": true,
    "message": "user has apps",
    "email": "[email protected]",
    "app": "greenhouse",
    "loc": "12ParleyVale",
    "role": "user"
}

Zones are set up by the original app author and it is a list of the things this app needs to function. Devs are set up by the app installer or owner for a particular location and connects the id's of the things the app needs to the devices and sensors/relays/timers/schedules that the device has to offer.

the parameters (ls, cfg and client)

ls connects you to the localStorage key that corresponds to cfg.appid. It provides a getItem() function that allows access to the token inside the localstorage value string. That token is sent inside a fetch to the server cfg.url.api . client is along for the ride so it can be connected to.

headers: {'Authorization': 'Bearer '+ lsh['token']},

what else useDevSpec does

Still within the useEffect hook, useDevSpec uses the useState hook once useDevSpec fetches the data from the server. The useState hooks sets the state of devs, zones and binfo. The last thing to get done within the useEffect is to connect the client to the mqtt broker and return as a way to shut it down if the component dismounts

return ()=>{
  didCancel=true
  client.disconnect()
}

In connecting to the mqtt broker, useDevZones sends the token from local storage as the connect 'password'. This only lets authorized users connect. In addition the broker uses the information in the token to determine which topics the user can subscribe and publish to.

monitorFocus (optional)

monitorFocus is the other way to connect and disconnect from the mqtt client. it takes a window object and turns the client on and off depending on focus or blur in cases where cutting off network traffic can help allay battery concerns.

setupSocket

Once you are connected, setupSocket runs. Carrying client, publish and devs from useDevSpecs or monitorFocus, it also needs to know what topics you want to pay attention to. ['srstate', 'sched', 'flags', 'timr'] are most of them. Basically these are the small and efficient type of messages that esp8266 and esp32 devices can handle decoding and encoding using c++. iot.sitebuilt.net has designed them.

srstate is sent whenever the sensor or relay value changes or if setpoints like hilimit or lolimit are changed.

CYURDOO4/srstate {"id":0, "darr":[64, 1, 81, 78], "new":0}

sched sends the schedule current running for a particular sesnor or relay. One of the devices built in timers is reserved for downloading the day's schedule from the mqtt broker->database at around midnight every day.

CYURDOO4/sched {"id":2,"aid":2,"ev":3,"numdata":1,"pro":[[0,0,1],[7,45,0],[19,0,1]]}

timr sends and array of timeleft on all relays that are run by a timers. "IStIMERoN" and "ISrELAYoN" is a binary representation of which relays and timers are currently on.

CYURD002/timr{"cREMENT":5,"IStIMERoN":4,"ISrELAYoN":5,"tIMElEFT":[0,0,26215,0,0]}

On every connection setupSocket subscribes to these topics and requests the current state of things. These subscriptions (and publishing rights too) are authorized at the mqtt broker using the token sent from useDevZones

processMessage

processMessage is called whenever the client.onMessageArrived calback fires. processMessage transforms the device/topic/payload data into and updated state for the zones the component is interested in. It returns a data package for that zone whenever the arriving message has anything to do with a zone you care about. Sometimes it returns undefined since the message has nothing to do with any zone you care about. onMessageArrived only updates the state of the zone that has new or changed data from processMessage

getDinfo

getDinfo gets the device information doing a reverse lookup from zone to devices and relay that is providing the data to that zone. This allows you to publish to a device/topic sr or id (sensor/relay ids) to change things on the device.

getZinfo

getZinfo gets the Zone information that you may want to use for displaying the pretty name of the zone or any iimages or other data that may be associated with that zone.

utility functions

startWhen(tzd_tza, delay)

When modify the days schedule of a device, you may be doing so from a different timezone. startWhen(tzd_tza, delay) takes browser time used by the app and transforms it to the current time as seen at the device. Timezones are sometimes expressed something like Fri May 24 2019 16:53:07 GMT-0400 (Eastern Daylight Time) where GMT-0400 is a representation of timezone modified by Day Light Savings Time, txd_tza uses that representation expressed as device_location_tz - app(browser)_location_tz. The second parameter is optional and would delay the start of the modified schedule. startWhen returns a time as an array [hr, min] like [17, 45]

endWhen(starttime, dur)

endWhen(starttime, dur) takes a starttime in the form returned by startWhen and outputs an end time in the same format calculated using duration in the format '1:15', returning a end time that is an hour and fifteen minutes later

newInterval(starttime, startval, endtime, endval)

In modifying a schedule you will be inserting into that schedule a new interval. The format used by the iot devices varies. An example of the simplest form is [[9,20,1], [13,15,0]] which would turn a relay on at 9:20am and off at 1:15pm. An example of a change to a sensor controlled relay would be [[17,15,72,70], [22,30,61,59]] which might do something like change the setpiont of a thermostat from ~71 degrees at 5:15pm and then lower the thermostat to ~60 degrees at 10:30pm. Here the relay calling for heat is controlled by the thermostat.

add2sched(sched, newInterval, tzd_tza)

add2sched modifies a schedule by inserting a new interval into it. The existing day's schedule is modified. Schedule events that have already happened are ignored. The new schedule that is returned starts from the moment you send it (although the new interval might not start rigth away, it might be delayed). Once the new interval completes then the remainder of the existing schedule will execute.

m2hm(min)

m2hm(min) takes a number and returns a string like 'hr:min'

refs

https://medium.com/@TeeFouad/a-simple-guide-to-publishing-an-npm-package-506dd7f3c47a