{"id":25629866,"url":"https://github.com/RomRider/node-divoom-timebox-evo","last_synced_at":"2026-06-10T15:30:16.506Z","repository":{"id":35092164,"uuid":"204760838","full_name":"RomRider/node-divoom-timebox-evo","owner":"RomRider","description":"A node module to generate messages for the Divoom Timebox Evo compatible with the module bluetooth-serial-port (https://github.com/eelcocramer/node-bluetooth-serial-port)","archived":false,"fork":false,"pushed_at":"2022-12-30T18:31:49.000Z","size":1153,"stargazers_count":137,"open_issues_count":17,"forks_count":16,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-02-09T07:41:24.255Z","etag":null,"topics":["divoom","evo","node","node-module","nodejs","timebox"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RomRider.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-08-27T18:03:17.000Z","updated_at":"2025-01-02T07:13:25.000Z","dependencies_parsed_at":"2023-01-15T13:39:45.424Z","dependency_job_id":null,"html_url":"https://github.com/RomRider/node-divoom-timebox-evo","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomRider%2Fnode-divoom-timebox-evo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomRider%2Fnode-divoom-timebox-evo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomRider%2Fnode-divoom-timebox-evo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RomRider%2Fnode-divoom-timebox-evo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RomRider","download_url":"https://codeload.github.com/RomRider/node-divoom-timebox-evo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240222512,"owners_count":19767472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["divoom","evo","node","node-module","nodejs","timebox"],"created_at":"2025-02-22T19:17:47.409Z","updated_at":"2026-06-10T15:30:16.470Z","avatar_url":"https://github.com/RomRider.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# node-divoom-timebox-evo\n\nThis module helps you generate the appropriate message to use against the divoom timebox evo.\n\nThe communication part is not implemented here and you can use the [bluetooth-serial-port](https://github.com/eelcocramer/node-bluetooth-serial-port) module to communicate with the timebox.\n\nHere's how you could do it:\n```js\nconst TIMEBOX_ADDRESS = \"11:22:33:44:55:66\";\nvar btSerial = new (require('bluetooth-serial-port')).BluetoothSerialPort();\nvar Divoom = require('node-divoom-timebox-evo');\n\nbtSerial.findSerialPortChannel(TIMEBOX_ADDRESS, function(channel) {\n  btSerial.connect(address, channel, function() {\n    console.log('connected');\n\n    btSerial.on('data', function(buffer) {\n      console.log(buffer.toString('ascii'));\n    });\n  }, function () {\n    console.log('cannot connect');\n  });\n}, function() {\n  console.log('found nothing');\n});\n\n\nvar d = (new Divoom.TimeboxEvo()).createRequest('animation');\nd.read('animation.gif').then(result =\u003e {\n  result.asBinaryBuffer().forEach(elt =\u003e {\n    btSerial.write(elt,\n      function(err, bytesWritten) {\n        if (err) console.log(err);\n      }\n    );\n  })\n}).catch(err =\u003e {\n  throw err;\n});\n\n```\n\n# Protocol Documentation\n\nSee [Protocol](PROTOCOL.md)\n\n# Install\n\n```sh\nnpm i node-divoom-timebox-evo\n```\n\n# Some Examples\n\nSee the complete documentation [here](https://romrider.github.io/node-divoom-timebox-evo/docs/)\n\n## Create a request\n\nYou'll always have to create a request first:\n```js\nvar Divoom = require('node-divoom-timebox-evo');\nvar d = (new Divoom.TimeboxEvo()).createRequest('REQUEST_TYPE');\n\n// d.messages.asBinaryBuffer() is an array of messages you have to send to your Timebox Evo over bluetooth as is. It returns an array of Buffers with Binary content.\nconsole.log(d.messages.asBinaryBuffer());\n```\n\nThe different `REQUEST_TYPE` are:\n* `cloud`: Will interact with the [Cloud Channel](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/cloudchannel.html)\n* `custom`: Will interact with the [Custom Channel](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/customchannel.html)\n* `lightning`: Will interact with the [Lightning Channel](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/lightningchannel.html)\n* `scoreboard`: Will interact with the [Scoreboard](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/scoreboardchannel.html)\n* `time`: Will interact with the [Time Channel](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/timechannel.html)\n* `vjeffect`: Will interact with the [VJ Effect Channel](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/vjeffectchannel.html)\n* `brightness`: Will set the [brightness](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/brightnesscommand.html)\n* `temp_weather`: Will set the [temperature and the weather](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/tempweathercommand.html)\n* `text`: Will display some [text](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/displaytext.html)\n* `picture` or `animation`: Will display a [picture or an animation](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/displayanimation.html)\n* `raw`: To send a [RAW](https://romrider.github.io/node-divoom-timebox-evo/docs/classes/timeboxevorequest.html) command\n\n## RAW Command\n\nThere's no need to calculate the size or the CRC of the messages. This will be done automatically.\n\n```js\nvar Divoom = require('node-divoom-timebox-evo');\n\nvar d = (new Divoom.TimeboxEvo()).createRequest('raw');\nd.push(\"4505\");\nd.messages.forEach(m =\u003e {\n  console.log(m.message);\n}) // Will display the list of messages as hexadecimals strings\nconsole.log(d.messages.asBinaryBuffer());\n```\n\n## Displaying an animation or a picture\n\n```js\nvar Divoom = require('node-divoom-timebox-evo');\n\nvar d = (new Divoom.TimeboxEvo()).createRequest('animation');\nd.read('file.png').then(result =\u003e {\n  console.log(result.asBinaryBuffer());\n  // send toSend to the Divoom\n  // use https://github.com/eelcocramer/node-bluetooth-serial-port\n}).catch(err =\u003e {\n  throw err;\n});\n```\n\n## Displaying Text\n\nYou have a number of baked in palettes:\n* `PALETTE_TEXT_ON_BACKGROUND(text?: ColorInput, background?: ColorInput)`: Sets the text color and the background color\n* `PALETTE_BLACK_ON_RAINBOW`: Black text on a rainbow background\n* `PALETTE_BLACK_ON_CMY_RAINBOW`: Black text on a CMY rainbow background\n\nAnd a number of baked in animations:\n* `ANIM_STATIC_BACKGROUND`: Background will not change color (useful with `PALETTE_TEXT_ON_BACKGROUND`)\n* `ANIM_UNI_GRADIANT_BACKGROUND`: Uniform background which will loop over all the colors of your palette\n* `ANIM_VERTICAL_GRADIANT_BACKGROUND`: Vertical gradient background which will loop over all the colors of your palette\n* `ANIM_HORIZONTAL_GRADIANT_BACKGROUND`: Horizontal gradient background which will loop over all the colors of your palette\n\n```js\nvar Divoom = require('node-divoom-timebox-evo');\n\nvar d = (new Divoom.TimeboxEvo()).createRequest('text', {text: \"Hi friends!\"});\nd.paletteFn = d.PALETTE_BLACK_ON_CMY_RAINBOW; // Baked in color palette, but you can define your own\nd.animFn = d.ANIM_HORIZONTAL_GRADIANT_BACKGROUND; // Baked in animation, but you can define your own\n\n// This contains what is required to bootstrap the display on the Timebox\nconsole.log(d.messages.asBinaryBuffer());\n\n// Then you have to send your animation frame by frame, I suggest that you do no go over 30 message per second, if you do, the timebox will disconnect.\n// This would generate 512 animation frames.\nfor (i = 0; i \u003c 512; i++){\n    console.log(d.getNextAnimationFrame().asBinaryBuffer());\n}\n```\n\nYou can define your own palette, the function has to return an array of 256 colors in Hex.\u003cbr/\u003e\nThe text's color will be the item `(background_color + 127) % 256`.\nThis is the code which generates the `PALETTE_BLACK_ON_RAINBOW`:\n```typescript\nd.paletteFn = function() {\n  function number2HexString(int: number): string {\n    return Math.round(int).toString(16).padStart(2, \"0\");\n  }\n\n  let palette: string[] = [];\n  const size = 127;\n  function sin_to_hex(i: number, phase: number) {\n    let sin = Math.sin(Math.PI / size * 2 * i + phase);\n    let int = Math.floor(sin * 127) + 128;\n    return number2HexString(int);\n  }\n\n  for (let i = 0; i \u003c size; i++) {\n    let red = sin_to_hex(i, 0 * Math.PI * 2 / 3); // 0   deg\n    let blue = sin_to_hex(i, 1 * Math.PI * 2 / 3); // 120 deg\n    let green = sin_to_hex(i, 2 * Math.PI * 2 / 3); // 240 deg\n    palette.push(red + green + blue);\n  }\n\n  // Completes the palette (everything after the 127th item in the array) with black color so that the text is actually only black\n  for (let i = palette.length; i \u003c 256; i++) {\n    palette.push(\"000000\");\n  }\n  return palette;\n}\n```\n\nYou can also define your own animation. It should be an array of 256 entries each one representing a pixel and referencing the index of the color to be displayed, taken from the palette. The function takes a frame number as a parameter.\u003cbr/\u003e\nExample which generated the horizontal gradient background (`ANIM_HORIZONTAL_GRADIANT_BACKGROUND`):\n```typescript\nd.animFn = function(frame) {\n  let pixelArray = [];\n  for (let y = 0; y \u003c 16; y++) {\n    for (let x = 0; x \u003c 16; x++) {\n      pixelArray.push((x + frame) % 127)\n    }\n  }\n  return pixelArray;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRomRider%2Fnode-divoom-timebox-evo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRomRider%2Fnode-divoom-timebox-evo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRomRider%2Fnode-divoom-timebox-evo/lists"}