I build a Zwift connected fan

(Sebastian Linz) #21

Hi Just

I’ve extended the documentation on GitHub. I’m looking forward to getting your feedback to improve documentation.

Best regards,




(Just Vervaart - Okimono Cycling Club) #22

Hi Sebastian, 

it took a while before i was able to test your setup. I got a new wifi router and it took a while to figure out that the particle core does not support wifi channels higher then #11 :( 

Anyhows, installation of the project was smooth (only problem i encountered was having to manually add the HttpClient to my Particle libraries). The node.js code seems to be running fine. I Get the front-end application on localhost:3000 and this is what the terminal is giving back. 

MacBook-Pro-van-NPO-2:fancontrol justvervaart$ npm install

up to date in 2.446s

MacBook-Pro-van-NPO-2:fancontrol justvervaart$ npm start

\> fancontrolapp@8.9.4 start /Users/justvervaart/Google Drive/Zwift/FanControl

\> node ./bin/www

Sat Feb 17 2018 09:46:29 GMT+0100 (CET) - debug: ZwiftAdapter.constructor()

Sat Feb 17 2018 09:46:33 GMT+0100 (CET) - debug: playerId: 120891

Sat Feb 17 2018 09:49:07 GMT+0100 (CET) - debug: /fanStateLevel3 fanState: 3, fanLevel: [3]

GET /fanStateLevel3 200 439.646 ms - 873

GET /stylesheets/style.css 304 5.565 ms - -

Sat Feb 17 2018 09:49:12 GMT+0100 (CET) - debug: /getFanLevel fanState: 3, fanLevel: [3]

GET /getFanLevel 200 3.584 ms - 28

But the Core seems to be unresponsive to input and when I select on Get Fan State I get this output: 


Any idea what is wrong? 






(Just Vervaart - Okimono Cycling Club) #23

ps. i also don’t see a folder with log files…


(Just Vervaart - Okimono Cycling Club) #24

Wait. I used a previous version of your Particle code. Just downloaded the new .ino file. Will test this afternoon again. 


(Just Vervaart - Okimono Cycling Club) #25

mmm. Stil no luck.



(Sebastian Linz) #26

Hi Just,

node.js-app are looking good. Maybe I’ve to fixe an error. While .gitignore ignores folder “./log” it isn’t added to repository and I should create this folder because watson (logging framework) is configured to log to file ./log/fancontrol.log. So if you create a folder “log” it should create the log-file.

Fan is set to level 3 because of the response given. So it’s somewhat between Photon and node.js-app.

If you have the possibility to connect the photon with your Mac by USB and have Putty installed, you can see what the Firmware is logging and if the response reaches the Photon. The response:


should start your fan with speed level 3 if relays are connected accordingly. Anyhow the fan should start. In Photon’s log you should see this statement:

httpRequestBodyHandler(data): _bodyHandler: 3_

and before:

loop(): HTTP Response Body: FCS3FLV3PWR0000HR000SPD00000

If you don’t see this statement, the response doesn’t reach the photon.

I propose you check this out and post the photon’s log here if you like.

Best regards,




(Just Vervaart - Okimono Cycling Club) #27

Hi Sebastian,

thx for the feedback. This is the output of the monitor. 

MacBook-Pro-van-NPO-2:fancontrol justvervaart$ particle serial monitor

Opening serial monitor for com port: "/dev/tty.usbmodem1411"

**Serial monitor opened successfully:**


FanController.setupPins(): entry.

FanController.setupPins(): RELAY1 mode OUTPUT

FanController.setupPins(): RELAY2 mode OUTPUT

FanController.setupPins(): RELAY3 mode OUTPUT

FanController.setupPins(): done.

FanController.setup(): pins setup

FanController.setupHttpRequest(): entry.

FanController.setupHttpRequest(): done.

loop(): number 1

loop(): Response status: -1

FanController.resetPins(): entry.

FanController.resetPins(): entry.

loop(): number 2

loop(): number 3

loop(): number 4

loop(): number 5

loop(): number 6

loop(): number 7

loop(): number 8   

(Sebastian Linz) #28

Hi Just,

for me it seems the issue is caused by the network connection between photon and your mac. Would you check the IP-address you’ve entered for your mac in the ino-file? Did you set the constant HOST_IP to the IP-address of the mac in your local network? Or the mac’s firewall settings are rejecting calls on port 3000. Sorry, I’m not a mac-user. Is there a firewall setting by default?




(Just Vervaart - Okimono Cycling Club) #29

Yes! Problem solved. I used the external wifi address of the router and not the internal address of the macbook. Stupid error. It now works like a charm! Great job and thx for sharing and help with setting up on my end.

Btw. is there a reason you only refresh every 5 seconds and not every second? 


(Sebastian Linz) #30

Hi Just,

that’s great! I started with 5 seconds. For me it’s enough. Maybe I’m changing to 3 seconds. I won’t go below 1 second, because the of request-response-cycle. But you can try out anyway.

Have fun and ride on



(Just Vervaart - Okimono Cycling Club) #31

Hi Sebastian,

i’v been tinkering with deploying the app on Heroku so it will work without having my laptop function as a server. The app runs fine, but connecting to the Particle is unsuccessful so far. Probably an ip/port thing again. Any experience with Heroku?

Greeting, Just


(Sebastian Linz) #32

Hi Just,

I had to look what Heroku is, because I didn’t know before. But at first I followed the same idea and deployed the node.js-app on GCP (google cloud platform). After 41 hours I had a bill round about 2 EUR so I discarded this approach.

It doesn’t bother me to run the node.js-app on my laptop, because the Zwift-Client has to run anyway.

To come back to your question. I didn’t knew Heroku before, but I used GCP which I would say is similiar. I liked the webhook very much and I think this should work for you too. You register the photon to be called back by the webhook and the webhook may call your node.js-app. I provided a simple REST-call by the node.js-app and returned a JSON-response, which could easily be handled by the webhook. You find more information about webhooks in particle’s documentation.

Best regards,



(J. Pohlman) #33

Is the API still working after GDPR?


(Sebastian Linz) #34

Hi J,

yesterday I rode and my fan worked fine.

Best regards,



(Rogerio Costa) #35


Please help-me?

(node:10344) UnhandledPromiseRejectionWarning: Error: Request failed with status code 401
    at createError (C:\fan01ode_modules\axios\lib\core\createError.js:16:15)
    at settle (C:\fan01ode_modules\axios\lib\core\settle.js:18:12)
    at IncomingMessage.handleStreamEnd (C:\fan01ode_modules\axios\lib\adapters\http.js:201:11)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1064:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
(node:10344) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 378)


(Sebastian Linz) #36

Hi Rogerio,

which solution are you using? Just’s or mine? If you like post the lines of code where the exception is thrown. I assume a missing catch in block in your code. Not sure.
Best regards


(Rogerio Costa) #37

Hi Sebastian, thanks!
I’m trying to use your code, but when I try to launch the error photon! I put the external ip as seen in the comments but when I check or flash the error
open file: visual Studio code
flash: build.particle.io
error “:9:24 HttpClient.h: No such file or directory


(Sebastian Linz) #38

Hi Rogerio,
just to be sure. Did you added the HttpClient-library to the environment? If not switch to libs view of photo’s dev environment, search for HttpClient and add it to your project. Maybe that’s the missing link.
Kind regards,


(Rogerio Costa) #39





I was able to add the httpclient, I can already access the “fan controller” the fan works by clicking on 1, 2 and 3, but when I use “z-simulation” or “z-workout” this error occurs: "could not resolve promise riderStatus "
I found the folder with my playid userxxxxx and "user name = email

Thank you again for your great attention


(Sebastian Linz) #40

Hi Rogerio,
if you haven’t found yet add your credentials config.js so the app is able to connect and login to the zwift interface.
Best regards,