How to call resource/bridge/switchon and /qr

I’ve been playing around with trying to reproduce the functionality of the fabman bridge. I’ve been working with the “Live API Documentation”, and have gotten most other api calls to work. But I’m not clear on how to call resource/bridge/switchon and /qr.

for switchon…
Authenticated with an Admin user api key
the url: https://fabman.io/api/v1/resources/2163/bridge/switch-on
(2163 is an id of a resource that has a bridge attached and set as Machine/switch)
the body:
{
“code”: “string”
}
(i dont know what “code” I am expected to put in here)

the response:
{
“statusCode”: 422,
“error”: “Unprocessable Entity”,
“message”: “Unknown device”,
“data”: {
“unknownDevice”: true
}
}
How do I properly use this API call?

For /qr
IIRC I have been successful calling this by passing in the same code which I saw after scanning the QR code on a legit FabMan Bridge. After scanning the QR code, I was sent to this URL https://fabman.io/members/{my user id}/equipment/{the equip id}/qr/QYMVW64MQR
Then playing with the API …
Authenticated using a bridge api key
url: https://fabman.io/api/v1/qr/QYMVW64MQR
I think it told me that the code was valid or invalid.

But how do I generate a valid QR code? I’m guess that recently generated codes are stored in Fabman, then when they are scanned, the /qr/ api is used to validate that it is an active code and the user can now be redirected to the /switchon api call, or a /switchon page on the fabman website.

Ultimately, what I’d like to do is have a printed out QR code on each machine. A user could scan this QR code and be directed to a /switchon page. After switching on the machine, a bridge/relay at the machine would be turned on.
I realize there are some security/safety issues with this, as someone could switchon a machine without being in the shop, but I hope to look at solutions for these after.
Thanks

Hi @mtags,

welcome to the forum! Seem like you already did a lot of work to figure things out. Kudos! :bowing_man:
Did I understand you correctly: you know how the regular access API for NFC cards works and just don’t know how QR access works?

Let’s start with the bad news: We have not yet updated the public bridge API to support the QR feature. We’ve only implemented it for our old, binary bridge API that isn’t documented because it’s much more difficult to use that the public API.

Why haven’t we updated the public API?

Because implementing the QR feature in your bridge firmware is much more involved and technically challenging than supporting the NFC access method and nobody has yet signalled interest in implementing it in their 3rd-party bridges – until you came along. :slight_smile:

So while we haven’t made this public yet, we’re willing to change this if it helps someone make their own awesome bridges.

So how does it work?

The QR feature works a bit differently than you expected. I’ll try to explain all the details below, so you can decide whether you want to go forward with this. Here’s what you need to know:

  1. The QR-Tags are generated on the bridge, not on the server.
  2. As you’ve probably seen, each tag contains a URL of the form https://fabman.io/qr/<access-code>.
  3. The access code is also generated on the bridge and contains base32-encoded binary data. There are a few different alphabets for base32. We’re using Crockford’s variant.
  4. The first 4 bytes of the decoded access code contain the bridge ID (2163 in your case) in big endian format.
  5. The remainder is a 6 byte nonce that’s randomly chosen by the bridge and rotated every 60 seconds. (More on that later.)
  6. In order for the server to be able to contact the bridge when someone presses “Switch on”, the bridge needs to keep a persistent connection to the server. We do this via long-polling on the “/heartbeat” endpoint. (Long-polling isn’t yet part of the public API, but you would append ?wait=true to signal that you’re interested in long-polling.)
  7. When the user presses on “Switch on”, the server queues a new activateWithNonce bridge command for that bridge. The command consists of the nonce and a unique ID.
  8. If there’s an active heartbeat long-poll, the command is sent immediately, otherwise it is sent as part of the next heartbeat response. (The command field is also not yet part of the public heartbeat API.)
  9. When the bridge receives the command, it checks if the nonce is still valid. Our bridge considers the last 3 nonces as valid, you have at most 3 minutes between scanning the code and pressing the button. We do this to ensure that people are really in front of the machine when they turn it on (and haven’t, eg., taken a picture of the code some time ago).
  10. If the nonce is valid, the bridge invalidates all currently active nonces and calls /access with a special key with {type: 'remoteAccess', token: <bridge-command-id>}. This key is only valid once, only for that bridge, and only for a short time.
  11. If the nonce is not valid, the bridge sends a commandError notification as part of its next heartbeat. (These notifications are also not yet part of the public API.) This lets the server inform the user in the browser that the code was expired (or invalid).

As you can see, this is much more work for the bridge than just calling “POST /access” with you NFC key. Getting it right and working reliably requires some programming skills, knowledge of network fundamentals – and effort.

If you’re nonetheless interested in implementing it, I’d be happy to do our part and update the public API so that it supports QR activations.
For your particular use-case you could use a static code instead of the nonce if you don’t mind people being able to re-use the same code over and over again.

Let me know if you have any further questions on this topic. I’d also be interested in learning more about the particular problem you’re trying to solve.

Thanks for the great response!
This may take some time to play around with, but I hope to report back.

Our interest in this is currently just to provide some more insight into who is using which machines and for how long. This will help with charging people for the use of our specialty machines, but also help us track usage and breakage :frowning: .
So my interest is just to create a low cost POC using some raspberry pis that we have kicking around, and see how things go.
We do have 2 legit fabman bridges, but probably reserve those for the doors for now, until we justify buying more.

Thanks again.

In that case, you should probably take a look at @roland’s Raspberry library for Fabman. It’s still quite early, but should help you get started building your own bridges.

For 3D printers, there’s also an Octoprint plugin that you can use instead of a normal bridge. It offers support for charging for material.

My understanding of the access code:
access code = base32_encode()//not real code
So 21631000 (resourceid=2163, random#=1000) results in ‘MM40R’
I used the python base32_crockford library to do this.
Is my understanding correct?
(Oddly, when I decrypt a real access code from one of our fabman bridges, I dont see the resourceid in the result.)

If I were to generate a qr code from this, it would be using the url ‘https://fabman.io/qr/MM40R

Now I should be able to go to a browser and enter https://fabman.io/qr/MM40R.
If I’m not logged in, it will ask me to.
The server will then decrypt the access code and grab the first 4 digits of the decrypted code and use that as the resource id.

I will then be redirected (in the browser) to https://fabman.io/members//equipment//qr/
I this case: https://fabman.io/members//equipment/2163/qr/MM40R
where I will be presented with the Switch On/Book screen.

I click ‘Switch On’. The server then replies to a bridge heartbeat, with the accesscode in the payload, that the bridge can turn on.
The bridge checks the accesscode is recent, and if it is, it turns on the relay.

Am I understanding this correctly?

If this is correct, two things arent working as expected.
https://fabman.io/qr/MM40R sends me to a 404, regardless if I am logged in or not.

A request to https://fabman.io/api/v1/bridge/heartbeat?wait=true by the bridge returns right away. I would expect the server to wait for a bit to see if any switchon messages come it, before replying to the request.

I had looked at the github HappylabWien/raspi-fabman, which was helpful in getting me to where I am. However, it is all NFC based, and I’m trying to figure out the QR code approach.
Thanks again.

Something must have gone wrong. MM40R decoded is a5 08 0c (in hex) which is only 3 bytes long. The ID alone should already be 4 bytes long – not just 4 digits (see point number 4 of my explanation).
When I encode only the ID 2163 as a 4 byte big endian integer to base32, I get 0000GWR.

The rest depends on how long you encode the nonce. We expect it to be 6 bytes – which I forgot to specify above. I’ve updated the description. Adding 1000 as 6 byte big endian after 2163 results in 000008730000000003e8 (in hex). Encode this in base32 and you’ll get 0000GWR0000000Z8. Try to reproduce that with your library as a first step.

Yes, the rest of the explanation seems correct. (Except for a minor detail that doesn’t matter: You will not be redirected to …/equipment/2163/qr/<full_code> but to …/equipment/2163/qr/<nonce_in_base32>.)

That’s because the code is not in the right format. (See above)

Yes, because the long-polling is not yet part of the public API – see point 6 of my explanation.

The crockford base32 python library that I was using wasnt giving me the results I needed, so I built my own based on the info here https://www.dcode.fr/crockford-base-32-encoding. I’ll hopefully post my code somewhere soon.
I can now consistently get the switchon page to work. When I now click the Switch On button, it says “Contacting Equipment…”. I have a bridge heartbeat running, but the nonce never comes back in the heartbeat. As you said it a previous post, the command (with the nonce in it) isnt currently part of the public api.
So I think I’ve gotten as far as I can for now.
If you’re interested in building the long-polling and heartbeat response with command+nonce, it would be appreciated.

Thanks for the help

1 Like