-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Adding DDP over WS, moving duplicate WS-connection to common.js #4997
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
Changes from 4 commits
4090af3
7cf935c
492d6b2
f8727a8
3cc4c8b
900babd
5e128cb
4183e60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -116,3 +116,52 @@ function uploadFile(fileObj, name) { | |
| fileObj.value = ''; | ||
| return false; | ||
| } | ||
| // connect to WebSocket, use parent WS or open new | ||
| function connectWs(onOpen) { | ||
| try { | ||
| if (top.window.ws && top.window.ws.readyState === WebSocket.OPEN) { | ||
| if (onOpen) onOpen(); | ||
| return top.window.ws; | ||
| } | ||
| } catch (e) {} | ||
|
|
||
| getLoc(); // ensure globals (loc, locip, locproto) are up to date | ||
| let url = loc ? getURL('/ws').replace("http","ws") : "ws://"+window.location.hostname+"/ws"; | ||
| let ws = new WebSocket(url); | ||
| ws.binaryType = "arraybuffer"; | ||
| if (onOpen) { ws.onopen = onOpen; } | ||
| return ws; | ||
| } | ||
|
|
||
| // send led colors to ESP using WebSocket and DDP protocol (RGB) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LED
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo |
||
| // ws: WebSocket object | ||
| // start: start pixel index | ||
| // len: number of pixels to send | ||
| // colors: Uint8Array with RGB values (3*len bytes) | ||
| function sendDDP(ws, start, len, colors) { | ||
| let maxDDPpx = 480; // must fit into one WebSocket frame of 1450 bytes, DDP header is 10 bytes -> 480 RGB pixels | ||
| if (!ws || ws.readyState !== WebSocket.OPEN) return false; | ||
| // send in chunks of maxDDPpx | ||
| for (let i = 0; i < len; i += maxDDPpx) { | ||
| let cnt = Math.min(maxDDPpx, len - i); | ||
| let off = (start + i) * 3; | ||
| let dLen = cnt * 3; | ||
| let cOff = i * 3; | ||
| let pkt = new Uint8Array(10 + dLen); | ||
| pkt[0] = 0x41; pkt[1] = 0x01; pkt[2] = 0x01; pkt[3] = 0; | ||
| pkt[4] = (off >> 24) & 255; | ||
| pkt[5] = (off >> 16) & 255; | ||
| pkt[6] = (off >> 8) & 255; | ||
| pkt[7] = off & 255; | ||
| pkt[8] = (dLen >> 8) & 255; | ||
| pkt[9] = dLen & 255; | ||
| pkt.set(colors.subarray(cOff, cOff + dLen), 10); | ||
| try { | ||
| ws.send(pkt.buffer); | ||
| } catch (e) { | ||
| console.error(e); | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
netmindz marked this conversation as resolved.
|
|
softhack007 marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,6 +71,15 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp | |
| // force broadcast in 500ms after updating client | ||
| //lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500); // ESP8266 does not like this | ||
| } | ||
| }else if (info->opcode == WS_BINARY) { | ||
| // interpreted binary data using DDP protocol | ||
| if (len < 10) return; // DDP header is 10 bytes | ||
| size_t ddpDataLen = (data[8] << 8) | data[9]; // data length in bytes from DDP header | ||
| uint8_t flags = data[0]; | ||
| if ((flags & DDP_TIMECODE_FLAG) ) ddpDataLen += 4; // timecode flag adds 4 bytes to data length | ||
| if (len < (10 + ddpDataLen)) return; // not enough data, prevent out of bounds read | ||
| // could be a valid DDP packet, forward to handler | ||
| handleE131Packet((e131_packet_t*)data, client->remoteIP(), P_DDP); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the only bit that makes me twitchy, the assumption that any binary messages are going to be DDP
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am no expert in protocol definition. How to solve it? if past experience has tought me anything it is not to try to predict the future of data usage ;)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've just checked the WebSocket protocol docs and you can send a Sec-WebSocket-Protocol http header, which if we used that then you also have a mechanism to know if the server supports what you are trying to send.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i.e the first byte maps to the function, which might itself support multiple messages
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. adding a header byte would work for me and since no applications exist yet that use binary streaming over WS there are no compatibility issues either. should I implement this approach? say something like:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite sure how auto detection would work, but reserving 0 for that sounds a good idea, beyond that do we already have any constant that identifiers DDP?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
for DDP or AR packets for example by looking at each packets header and finding unique identifiers, but this was just a thought, no real usecase in mind. I will go ahead and implement a minimal version
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You definitely could do some form of auto detection, my query was more how to ensure proper encapsulation and separation of concerns within the code if we did that. |
||
| } | ||
|
DedeHai marked this conversation as resolved.
|
||
| } else { | ||
| //message is comprised of multiple frames or the frame is split into multiple packets | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.