-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Experiment: read sensor data with mode informations #60
Conversation
this._activatePortDevice(port.value, type, this._getModeForDeviceType(type), 0x00); | ||
this.subscribe(port.id, this._getModeForDeviceType(type)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changed only to have the exact same result using manual subscribe or autosubscribe.
this._sendPortInformationRequest(data[3]); | ||
} | ||
this._sendPortInformationRequest(data[3]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ask for port information even if no debug flag to get parsing format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I specifically removed it to avoid unnecessary radio static, of course since you actually use this information it cannot be avoided (though it could be trimmed to the messages you use - name and data type).
I love this - it's something I'd hoped to try experimenting with but again you guys beat me to it. :) One thing I notice though is that the ginormous switch statement with emits looks very repetitive. One solution might be to have a mapping of modes to human-friendly emit types, and use the ES6 spread operator to spread out the |
I tried to do this first but there is some special cases where it does not work very well :
also, it miss the event documentation that should take place there. I will look for a good compromise. |
I tried something to remove the event big switch. It hits me that with the #49 and specific class per device the edge cases would disappear. I still don't understand how to read modes sequentially. I think |
Nicely done @aileo. I was also thinking about reworking the sensor reading code. I had some similar ideas, but overall I would try to go more radical, but I am not sure how viable would that be. Specifically I would try to make
This is obviously port mode information and the file name contains the device type number and its software and hardware version. This suggests that Lego's official SDK:
|
this._sendPortInformationRequest(data[3]); | ||
} | ||
this._sendPortInformationRequest(data[3]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I specifically removed it to avoid unnecessary radio static, of course since you actually use this information it cannot be avoided (though it could be trimmed to the messages you use - name and data type).
* @param {number} z | ||
*/ | ||
ACCEL: "acceleration", | ||
ROT: "acceleration" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C+ hub 'ROT' mode is angular velocity (or rotation speed), acceleration is reported by the 'GRV' mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I totaly missed those, I did not see GRV mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is on the previously not supported port 0x61 mode 0, I added it in a recently merged PR.
} | ||
|
||
} | ||
|
||
|
||
private _emitSensorEvent(port: Port, mode: IPortMode, values: number[]) { | ||
const modeToEvent: { [key: string]: string } = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea with the event name map, but I think it would be cool it the users could also subscribe to ports using these names. Otherwise you need to remember that to fire distance
events you need to use PROX
or LPF2-DETECT
depending on the device used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is aleady this.emit("sensor", port.id, mode, values);
and it would make a lot of duplicated events, I don't know what approach should be adopted.
} else if (mode.name === "POS" && port.type === Consts.DeviceType.CONTROL_PLUS_TILT) { | ||
this.emit("angle", port.id, ...values); | ||
} else if (modeToEvent[mode.name]) { | ||
this.emit(modeToEvent[mode.name], port.id, ...values); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should ideally also normalize the values according to min/max raw and si unit. For example accel in boost hub 1G = 65 while in C+ hub 1G=4096.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any link to the device/firmware mode information files ? I would try to work on a normalization helper to convert values.
Agreed. I'm about to push my (very) WIP branch with these changes so you can take a look at the approach, but I think it should allow for per device mode types.
I think some kind of counter would be required, ie. device reports 4 modes (totalModes), so increment a counter (reportedModes) whenever a piece of mode info comes in. When reportedModes => totalModes, resolve a promise so that higher order code can continue. |
This is fantastic idea, I hadn't thought about that! I'm literally going to start implement this in my working branch for #49 - I was about to work in subscribe methods, but this is a step up. The question of combined ports becomes an issue - ie. If you attach an event handler for "color", and one for "reflectivity", it should probably set up combined mode for the device so both can be reported. But this can be tackled later (using @aileo's code here in this PR as a base) - v1 can be one at a time.
Can BLE drop messages? I thought it was a "reliable" transport protocol like TCP, however I understand that some devices drop mesages in low memory situations. However how common will this be with PUP devices?
This is actually a great idea (essentially caching the information for known firmware versions). We could probably follow this approach? |
Thanks @nutki for the review, you always find all my mistakes, and they are numerous.
I think it could be great as it makes events/mode relation very simple for the user. My concerns are over the complexity it adds to the lib:
|
@aileo I think you presented perfectly good solutions to those concerns. In the event the user isn't properly removing listeners, and until combined mode is added, the "last added wins" approach can work, as it's an existing paradigm that makes sense to users (up to now in this lib, you could only set one mode at a time). @nutki I've actually implemented your suggestion in #61 and I think it's a great solution. Currently I'm not working on combined modes (this is MVP1) and still need to implement unsubscribe, but it's working great. |
@aileo I'd actually love to know your thoughts on how to merge some of this with #61. I've managed to eliminate the "Big Ugly Switch Statement(TM)" of mode numbers to event names by creating a map of them and having it handled automatically, but for parsing of the sensor messages, I still have a switch statement. I think maybe some of this could work with that, by reverse looking up the event name from the currently set mode? Some special cases could still be required, but I wonder if it could simplify it greatly? |
I think we have to drop the part of this PR where it get parsing information from mode info as it lead to big latency (and it totally rely on not missing any message). Some sort of configuration could do the job (I don't think mode are updated that often and we could maintain some firmware related configuration like @nutki showed here if needed. From what I investigated about modes in #56 , modes do not have the same position (number, id) on every hub (L/XL motors have load mode on PUP and C+ at 0x04 and CALIB at 0x05 but CALIB is at 0x04 and STATS at 0x05 on Boost). I think we have a list of modes for each device type with :
We can map event name to mode name or add directly event name to the modes configuration. I would make this configuration a static attribute of each device class instead of passing it to I would also defer the parsing to the device class when it comes to device sensor messages (or other pure device messages). This way the edge cases would be handle by the device itself and this could simplify some test suite implementation :) . The first step is to collect all modes information for all devices on all hubs. I will do some as soon as I get my hands back on my hubs. Side note : talking about "Big Ugly Switch Statement(TM)", a device type to constructor map would also remove the one in |
#97 is way better than this |
Once again this is not meant to be merged as it breaks everything.
Since the LWP3 exposes mode information with name and data format for parsing, I tried to implement some kind of "auto parsing":
sensor
event with mode name and raw parsed data array (which allow to listen to events not handled by the lib)BUT: It does not work very well as I don't know how to get the mode information before the
attach
event is emited. As is, it just ignore sensor events until the mode information got collected...If anyone see value in this and wants to help, I would be very happy to know if there is a way to make it reliable.