{"id":24313944,"url":"https://github.com/emiliobondioli/flipper","last_synced_at":"2025-08-02T10:36:48.800Z","repository":{"id":33416477,"uuid":"282434645","full_name":"emiliobondioli/flipper","owner":"emiliobondioli","description":"Flip dot controller for AlfaZeta XY5 flip dot panels","archived":false,"fork":false,"pushed_at":"2023-10-27T09:03:48.000Z","size":451,"stargazers_count":9,"open_issues_count":3,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-06-24T11:17:21.797Z","etag":null,"topics":["client","controller","electronics","javascript","middleware","nodejs","vite","websocket"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emiliobondioli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-07-25T11:57:42.000Z","updated_at":"2024-01-23T05:56:33.000Z","dependencies_parsed_at":"2022-08-07T21:15:19.966Z","dependency_job_id":"b34dc44b-e44f-4806-acbd-dec21b1bbd6e","html_url":"https://github.com/emiliobondioli/flipper","commit_stats":{"total_commits":91,"total_committers":2,"mean_commits":45.5,"dds":0.04395604395604391,"last_synced_commit":"92b4c04411286cbced10d45e92605b7b1fcdb7f6"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/emiliobondioli/flipper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emiliobondioli%2Fflipper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emiliobondioli%2Fflipper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emiliobondioli%2Fflipper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emiliobondioli%2Fflipper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emiliobondioli","download_url":"https://codeload.github.com/emiliobondioli/flipper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emiliobondioli%2Fflipper/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268372163,"owners_count":24239820,"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","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["client","controller","electronics","javascript","middleware","nodejs","vite","websocket"],"created_at":"2025-01-17T09:14:59.174Z","updated_at":"2025-08-02T10:36:48.778Z","avatar_url":"https://github.com/emiliobondioli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flipper\n\nFlip dot controller library - to be used with [AlfaZeta XY5](https://flipdots.com/en/products-services/flip-dot-boards-xy5/)\n\n## Install\n\n```\nnpm i @ebondioli/flipper\n```\n\n## Basic usage\nThe `Controller` module is required for serial communication with the flip dot panels. Since it requires the `serialport` module it must be run in NodeJS context.\n\n### Standalone\nFlipper can be run in a NodeJS script using the `Controller` and `Stage` modules as follows:\n\n```js\nconst { Controller, Stage } = require('@ebondioli/flipper/controller')\n// the controller will continuously write its buffer to the configured serial port\nconst controller = new Controller({\n    serial: {\n        port: '/dev/ttyUSB0',\n        baudRate: 57600\n    },\n    mock: false,    // if true disables serial communication\n    debug: false    // enable debug logging\n})\nconst stage = new Stage({    \n  panels: [\n      // panel list, see below Panels section for options\n  ],\n  // configuration for different panel types and dimensions, defaults are for AlfaZeta XY5\n  panelConfig: {\n      width: 28,\n      height: 7,\n      header: [0x80, 0x85],\n      terminator: [0x8F]\n  }\n})\n// flips ON the dot at (0,0)\nstage.set(0, 0, true);\n// flips OFF the dot at (0,1)\nstage.set(0, 1, false);\n// sends the updated buffer to the controller\ncontroller.set(stage.buffer)\n```\n\n### Websocket Client/Server\nIf you need to work in the browser, a simple Websocket client/server solution is provided:\n\n#### NodeJS middleware\n```js\nconst { Controller, Server } = require('@ebondioli/flipper/controller')\nconst controller = new Controller({ /* options */ })\n// the server module will automatically update the controller buffer when receiving data\nconst server = new Server(controller, { \n  socket: {\n      url: 'ws://localhost',\n      port: 3001\n  },\n  mock: false,\n  debug: false\n})\n```\n#### Browser script\n`Client` extends the `Stage` module and allows for easy websocket communication\n```js\nimport { Client } from \"@ebondioli/flipper/browser\";\nconst client = new Client({\n  socket: {\n    url: \"ws://localhost\",\n    port: 3001,\n  },\n  stage: { \n    // stage config, see above for options \n  },\n  mock: false, // if true disables socket communication\n});\n// flips ON the dot at (0,0)\nclient.set(0, 0, true);       \n// sends the current buffer to the socket server, usually called on an interval or requestAnimationFrame\nclient.send();                        \n```\n## Panels\nA panels config object is required to correctly convert the stage's dots to bytes\n```js\nconst panels = [\n  {\n    // panel address in binary\n    address: 0b01,\n    // panel dimensions\n    bounds: {\n      x: 0,\n      y: 0,\n      width: 28,\n      height: 7,\n    },\n    // used to align the simulator view with the actual panels positioning\n    offset: {\n      x: 0,\n      y: 0,\n    },\n  },\n]\n```\n\n## Stage\nThe `Stage` module translates x/y coordinates to the related flip dot bytes. `set`, `get` and `fill` methods are used to interact with the dots.\n\n```js\nclient.set(0, 0, true | false);       // flips or unflips a single dot at (0,0)\nclient.toggle(0, 0);                  // toggles a single dot at (0,0)\nclient.fill(true | false | \"toggle\"); // flips, unflips or toggles all dots\n```\n\n## Simulator\n\nA simple simulator is provided as a separate module for ease of development. It connects to the `client` module and replicates the panels configuration and positioning.\n\nExample usage in a browser/frontend app:\n\n```js\nimport { Client, Simulator } from \"@ebondioli/flipper/browser\";\nimport \"@ebondioli/flipper/style\";\n\nconst client = new Client(config);\n// istantiate the simulator passing the client instance to connect to and a dom element where to mount it\nconst simulator = new Simulator(client, document.querySelector(\"#app\"));\n\n// call after the client has been updated to update the simulator view, e.g. in an interval or requestAnimationFrame\nsimulator.update();\n```\n\nThe default css for the simulator can be included using:\n\n```js\nimport \"@ebondioli/flipper/simulator/style\";\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femiliobondioli%2Fflipper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femiliobondioli%2Fflipper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femiliobondioli%2Fflipper/lists"}