{"id":15586265,"url":"https://github.com/alecdotninja/flic","last_synced_at":"2025-04-24T04:40:32.151Z","repository":{"id":56846742,"uuid":"65449744","full_name":"alecdotninja/flic","owner":"alecdotninja","description":"An unofficial Ruby implementation of the fliclib (use Flic IoT buttons in Ruby!)","archived":false,"fork":false,"pushed_at":"2016-12-16T03:04:24.000Z","size":74,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-07T21:17:42.051Z","etag":null,"topics":["bluetooth","flic","flic-buttons","fliclib","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/alecdotninja.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-08-11T07:50:09.000Z","updated_at":"2024-01-11T17:12:03.000Z","dependencies_parsed_at":"2022-09-09T01:00:28.723Z","dependency_job_id":null,"html_url":"https://github.com/alecdotninja/flic","commit_stats":null,"previous_names":["anarchocurious/flic"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecdotninja%2Fflic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecdotninja%2Fflic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecdotninja%2Fflic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecdotninja%2Fflic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alecdotninja","download_url":"https://codeload.github.com/alecdotninja/flic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250566439,"owners_count":21451227,"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":["bluetooth","flic","flic-buttons","fliclib","ruby"],"created_at":"2024-10-02T21:21:32.749Z","updated_at":"2025-04-24T04:40:32.134Z","avatar_url":"https://github.com/alecdotninja.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flic\nFlic is a lightweight but thread-safe Ruby implementation of the [Fliclib](https://github.com/50ButtonsEach/fliclib-linux-hci/blob/master/ProtocolDocumentation.md). It interfaces with [flicd](https://github.com/50ButtonsEach/fliclib-linux-hci), and allows [Flic buttons](https://flic.io/) to be used as an input for Ruby applications.\n\n## Installation\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'flic'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install flic\n\n## Simple Usage\nThe easiest way to get up an running is to use `Flic::SimpleClient`. It is a thin wrapper around `Flic::Client` that provides a simplified, synchronous API for the most intuative uses of a Flic button.\n\n### Establishing a connection to `flicd`\nBy default, `flicd` binds to `localhost` on port `5551`. These are also the defaults for `Filc::SimpleClient`. This means that if you are running `flicd` on your local machine, establishing a connection is as easy as creating a new instance of `Flic::SimpleClient`. For other configurations, you can initialize `Flic::SimpleCient` with host and port. For example, `Flic::SimpleClient.new('192.168.1.200', 5553)` will open a connection to `flicd` on `192.168.1.200` listening on port `5553`.\n\n### Getting a list of buttons\nTo get a list of verified buttons (buttons associated and ready to be used with a given `flicd`), call `Flic::SimpleClient#buttons`. This will return a list of button's bluetooth addresses.\n\n### Connecting a new button\nA button must be in public mode before it can be added. To put a button in public mode, press and hold it for at least 7 seconds. `Flic::SimpleClient#connect_button` will return the bluetooh address of the button that was added or `nil` if no button was added.\n\n### Disconnecting a button\nSimilarly, a button may be disconnected by passing `Flic::SimpleClient#disconnect_button` a button's bluetooth address.\n\n### Listening for button events\n`Flic::SimpleClient#listen` accepts a latency mode (`:low`, `:normal`, or `:high`) as it's first argument and button bluetooth addresses as its other arguments. For each event that occurs to those buttons, it yields the bluetooth address of the button responsible for a given event, the type of click involved in the event (`:button_down`, `:button_up`, `:button_single_click`, `:button_double_click`, or `:button_hold`), the time in seconds since the event occured, and whether the event was queued. **It will block until the connection is closed or the block raises some other exception.**\n\n### Closing the connection to `flicd`\nTo gracefully cleanup all connection channels and close the socket connection, call `Flic::SimpleClient#shutdown`. Once a `Flic::SimpleClient` has been shutdown it will close the underlying socket and cannot be used anymore.\n\n### Example\nThis is the script that I wrote to allow some of my Flic buttons to control Wink-enabled smart devices in home.\n```ruby\n#!/usr/bin/env ruby\n\nrequire 'bundler/setup'\nrequire 'flic'\nrequire 'httparty'\n\n# These bluetooth addresses were obtained from SimpleClient#connect_button\nCOFFEE_TABLE_BUTTON  = 'XX:XX:XX:XX:XX:XX'\nLIVING_ROOM_BUTTON   = 'XX:XX:XX:XX:XX:XX'\nBEDROOM_BUTTON       = 'XX:XX:XX:XX:XX:XX'\nNIGHTSTAND_BUTTON    = 'XX:XX:XX:XX:XX:XX'\n\n# Obtained from https://winkbearertoken.appspot.com/\nWINK_REQUEST_OPTIONS = {\n    headers: {\n        Authorization: 'Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n    }\n}\n\n# Get a list of all scenes\n# HTTParty.get('https://api.wink.com/users/me/scenes', WINK_REQUEST_OPTIONS)\nSCENES = {\n    arriving:                     'XXXXXXX',\n    leaving:                      'XXXXXXX',\n    sleeping:                     'XXXXXXX',\n    turn_on_living_room_lights:   'XXXXXXX',\n    turn_off_living_room_lights:  'XXXXXXX',\n    turn_on_bedroom_lights:       'XXXXXXX',\n    turn_off_bedroom_lights:      'XXXXXXX',\n    waking_up:                    'XXXXXXX'\n}\n\nACTIONS = {\n    COFFEE_TABLE_BUTTON =\u003e {\n        button_single_click:  :turn_on_living_room_lights,\n        button_double_click:  :turn_off_living_room_lights,\n        button_hold:          :leaving\n    },\n    LIVING_ROOM_BUTTON =\u003e {\n        button_single_click:  :turn_on_living_room_lights,\n        button_double_click:  :turn_off_living_room_lights,\n        button_hold:          :leaving\n    },\n    BEDROOM_BUTTON =\u003e {\n        button_single_click:  :turn_on_bedroom_lights,\n        button_double_click:  :turn_off_bedroom_lights,\n        button_hold:          :sleeping\n    },\n    NIGHTSTAND_BUTTON =\u003e {\n        button_single_click:  :turn_on_bedroom_lights,\n        button_double_click:  :turn_off_bedroom_lights,\n        button_hold:          :waking_up\n    }\n}\n\n# Let's get this party started!\nbegin\n  puts '[*] Opening a connection to flicd...'\n  client = Flic::SimpleClient.new\n\n  puts '[*] Entering main loop'\n  client.listen(:low, COFFEE_TABLE_BUTTON, LIVING_ROOM_BUTTON, BEDROOM_BUTTON, NIGHTSTAND_BUTTON) do |button, event, latency|\n    begin\n      scene = SCENES[ACTIONS[button][event]]\n\n      if scene \u0026\u0026 latency \u003c 5\n        puts \"[*] [#{button}] Handling #{event}\"\n\n        HTTParty.post(\"https://api.wink.com/scenes/#{scene}/activate\", WINK_REQUEST_OPTIONS)\n      else\n        puts \"[*] [#{button}] Ignoring #{event}\"\n      end\n    rescue StandardError =\u003e error\n      puts \"[!] Whoops! `#{error.inspect}` occured while processing #{event} on #{button}.\"\n    end\n  end\nrescue StandardError =\u003e error\n  puts \"[!] Whoops! #{error.inspect} occured. Wait for a few seconds and restart everything.\"\n  sleep 3\n\n  retry\nrescue Interrupt\n  puts '[*] Shutting down gracefully because of an interrupt'\n\n  client.shutdown\nend\n```\n\n## Advanced Usage\nThe interface of `Flic::Client` closely mirrors [the official Java implimentation](https://github.com/50ButtonsEach/fliclib-linux-hci/tree/master/clientlib/java). Unlike `Flic::SimpleClient`, none of it's methods are blocking except `Flic::Client#handle_next_event` which blocks until the next event is recevied and dispatches it to the approprate handlers and `Flic::Client#enter_main_loop` which blocks until the client is shutdown and dispatches events as they are received. Ideally, `Flic::Client#enter_main_loop` should be run in a dedicated networking / event dispatch thread.\n\n\n## Contributing\nBug reports and pull requests are welcome on GitHub at https://github.com/anarchocurious/flic.\n\n## License\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecdotninja%2Fflic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falecdotninja%2Fflic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecdotninja%2Fflic/lists"}