Claiming with claimDevice() and getClaimCode()

Hi,

I'm in the process of modifying our particle-sdk based mobile apps (I know) to support new products that will be use the Photon 2. I've modified the BLE examples for both android and iOS and am in the process of incorporating them into our current apps, with a simple selection for a user to pick to go down the old softAP path or the new BLE one. (Eventually we'd like to rewrite the app using something like Expo and follow the recommended api-calls-from-your-server model, but we didn't think we had time to completely rewrite our old app from scratch while also implementing softAP/BLE.)

Everything is seems to be working so far, but one key difference is that I'm not using the claim code mechanism and am instead trying to simply make a claimDevice() api call with the customer's product-specific access token. It works when the device is unclaimed, it seems like my test customer accounts can't claim from each other in the same way our Photon product customers can. I also tried adding the ?request_transfer=true but that didn't seem to work either. Looking at some previous posts (here and here as well as the old device claiming process) I think I've just been misunderstanding the claim code. Is it what allows customers of a product to claim from each other? If that's the case and I can't use claimDevice() and should just add the claim code protobuf to my BLE steps and we should be good, but I wanted to check to make sure I wasn't doing something else incorrectly first.

Using the device claim cloud API, a device can only be claimed if it is unclaimed, or claimed to the same user.

Transferring claiming requires the that original owner reply to an email that is sent. However I think this only works with developer accounts, not customer accounts.

Claim codes, on the other hand, can "steal" claiming from an other user or customer, as long as the device was originally not in a product, or is being moved within the same product.

The reason for this is that the device claim cloud API can be run from anywhere, so there needs to be some security to prevent stealing claiming of others' devices. When using the claim code, it can only be set by Soft AP (in listening mode), authenticated BLE, or by USB, which all require physical access or near physical access to the device, so the bar is lower for transferring claiming.

Awesome, thanks Rick. I'll add the that control request and see if we can get the same results as our Photon product. I know the concept of claiming is on the way out but it would be nice if there was a product claimDevice() that could claim the device on behalf of a customer.

Transferring claiming requires the that original owner reply to an email that is sent. However I think this only works with developer accounts, not customer accounts.

This does seem to be the case, as I was able to get this to work with my developer account but not with my test customer accounts.

I've added set the claim code on a P2 device for a product, but it doesn't seem to claim the device once connected. Probably should've asked this first but are claim codes supported on the P2? I can see that it is responding to the control request and the result is 0 which should mean that it worked correctly. Are there any other steps besides generating the claim code (with the productId and the user's access token) and sending it to the P2 through the set claim code control request?

I didn't check your exact scenario, but claim codes do work on the P2 sometimes and are able to force claim a device. Look for this in the USB serial debug log:

0000035159 [system] INFO: Send spark/device/claim/code event for code xxxxxxxx5GvuPJBVDv3cf0Nq1TjyJLgeETsKHR/36QogoGZ0ipy0EnFnjCSMZ5m

One difference is that I set the claim code using DFU instead of the control request. But it looks like the control request handler is implemented and it should work properly. The other is that I used a developer account claim code, not a product claim code, but that's handled on the cloud side not the device side so I don't expect any differences on the P2 for that.

However, I think there is a problem when using claim codes when the device has recently connected to the cloud and resumes an existing session. In this case, it appears that the claim code is not sent. I suspect that is what you are experiencing. This probably never came up before because the P1/Photon 1 can't do a session resume and cellular devices don't use claim codes.

0000033624 [comm.protocol.handshake] INFO: Skipping HELLO message
0000033807 [system] INFO: cloud connected from existing session.

That's very interesting. Sure enough, powering up the P2 this morning sent the claim code

0000015435 [system] INFO: Send spark/device/claim/code event for code xxxxxxxxSGVmI0I8+rBd/8MB9gj9feyU1dFJCPSns4Gb+CaqgdZXej67kjIKlOo
0000017861 [system] TRACE: Claim code received by the cloud and cleared locally.

That's great! Two ideas - Can I force a new cloud session on something like a network_credentials_added event? Or, could i look for cloud_status_session_resume and directly publish a claim event like what's in system_cloud_internal.cpp?

char buf[CLAIM_CODE_SIZE + 1];
if (!HAL_Get_Claim_Code(buf, sizeof(buf)) && buf[0] != 0 && (uint8_t)buf[0] != 0xff) {
      LOG(INFO,"Send spark/device/claim/code event for code %s", buf);
      publishEvent("spark/device/claim/code", buf);
}

Not sure how what header I'd need to include to access the HAL_Get_Claim_Code function since I can't seem to simply include system_cloud_internal.h. If it's possible to try what I'm doing please let me know.

I was able to get this to work by having the network_credentials_added event tell me if we had new credentials (and likely a claim code), waiting for the network to then disconnect at least once, and then waiting for it to connect again before sending

Particle.publish("spark/device/session/end", "", PRIVATE);

To force a new cloud session. I had to wait for re connection after a disconnect because it would try to send it while connection after a network_credentials_added event, it would just get lost because it would happen during the handshake of a new session. On the new session the claim code gets send and we're all set!