{"id":22062485,"url":"https://github.com/pmiddend/hs-tango","last_synced_at":"2026-02-19T00:02:10.906Z","repository":{"id":249656855,"uuid":"675228166","full_name":"pmiddend/hs-tango","owner":"pmiddend","description":"Haskell bindings to the Tango controls system","archived":false,"fork":false,"pushed_at":"2025-03-07T09:47:28.000Z","size":462,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-12T22:46:17.947Z","etag":null,"topics":["haskell","tango-controls"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/hs-tango","language":"Haskell","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/pmiddend.png","metadata":{"files":{"readme":"README.org","changelog":"Changelog","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-06T08:03:31.000Z","updated_at":"2025-03-07T09:47:32.000Z","dependencies_parsed_at":"2024-10-28T09:55:35.997Z","dependency_job_id":"099af7a9-9b87-4039-9ca4-3c7d3c78446e","html_url":"https://github.com/pmiddend/hs-tango","commit_stats":null,"previous_names":["pmiddend/tango-hs","pmiddend/hs-tango"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmiddend%2Fhs-tango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmiddend%2Fhs-tango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmiddend%2Fhs-tango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmiddend%2Fhs-tango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmiddend","download_url":"https://codeload.github.com/pmiddend/hs-tango/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253837387,"owners_count":21971981,"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":["haskell","tango-controls"],"created_at":"2024-11-30T18:20:26.830Z","updated_at":"2026-02-19T00:02:05.871Z","avatar_url":"https://github.com/pmiddend.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"* hs-tango\n\n[[https://www.gnu.org/licenses/gpl-3.0][https://img.shields.io/badge/License-GPLv3-blue.svg]]\n[[Hackage][https://img.shields.io/hackage/v/hs-tango.svg]]\n[[CI][https://github.com/pmiddend/hs-tango/actions/workflows/build-with-ubuntu.yaml/badge.svg]]\n\n\n** How to install\n*** General instructions\nA simple =cabal install hs-tango= should suffice to build and install the library, as you would for any other Haskell library. Of course, you need to have the development packages for Tango (namely \"cpptango\") installed.\n\nThe [[https://tango-controls.readthedocs.io/en/latest/installation/tango-on-linux.html#debian-ubuntu][Tango documentation]] has instructions on how to install Tango for different operating systems. On *Debian* and *Ubuntu*, for example, you can do =apt install libtango-dev=.\n*** With Nix\n\nIf you're using the Nix package manager, you have to enable flakes, and then use the accompanying =flake.nix=. To get Tango, it uses the [[https://gitlab.desy.de/cfel-sc-public/tango-flake][tango-flake]] from your truly. You can simply clone the repository, do =nix develop=, and then =cabal build=.\n** Usage\n*** Client, reading attributes\n\nThere is haddock documentation available. But just to illustrate how to use the library, here's a little client example:\n\n#+begin_src haskell\n{-# LANGUAGE OverloadedStrings #-}\n\nmodule Main where\n\nimport Tango.Client(\n  parseTangoUrl,\n  withDeviceProxy,\n  getTimeout,\n  AttributeName(..),\n  readBoolAttribute,\n  readBoolSpectrumAttribute\n)\n\nmain :: IO ()\nmain =\n  case parseTangoUrl \"sys/tg_test/1\" of\n    Left e -\u003e error \"couldn't resolve tango URL\"\n    Right deviceAddress -\u003e withDeviceProxy deviceAddress $ \\proxy -\u003e do\n      timeout \u003c- getTimeout proxy\n      putStrLn $ \"proxy timeout is \" \u003c\u003e show timeout\n\n      booleanResult \u003c- readBoolAttribute proxy (AttributeName \"boolean_scalar\")\n      putStrLn $ \"boolean_scalar is \" \u003c\u003e show booleanResult\n\n      booleanResultBetter \u003c- readBoolAttribute proxy (AttributeName \"boolean_scalar\")\n      putStrLn $ \"boolean_scalar better is \" \u003c\u003e show booleanResultBetter\n\n      booleanSpectrumResult \u003c- readBoolSpectrumAttribute proxy (AttributeName \"boolean_spectrum\")\n      putStrLn $ \"boolean_spectrum is \" \u003c\u003e show booleanSpectrumResult\n#+end_src\n*** Client, subscribing to events\n\nIn this example, we are subscribing to changes in the attribute =boolean_scalar= and waiting for two changes (the =forM_= loop).\n\n#+begin_src haskell\n{-# LANGUAGE BlockArguments #-}\n{-# LANGUAGE ImportQualifiedPost #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n\nmodule Main where\n\nimport Control.Concurrent (newChan, readChan, writeChan)\nimport Control.Monad (forM_)\nimport Control.Monad.IO.Class (liftIO)\nimport Data.Int (Int16)\nimport Data.Text.IO qualified as TIO\nimport Tango.Client\n\nmain =\n  case parseTangoUrl \"sys/tg_test/1\" of\n    Left e -\u003e error \"couldn't resolve tango URL\"\n    Right deviceAddress -\u003e withDeviceProxy deviceAddress \\proxy -\u003e do\n      timeout \u003c- getTimeout proxy\n\n      chan \u003c- newChan\n\n      let attributeName = AttributeName \"boolean_scalar\"\n          eventCallback attribute bool = liftIO do\n            boolValue \u003c- readBoolAttribute proxy attributeName\n            putStrLn $ \"got a change: \" \u003c\u003e show boolValue\n            writeChan chan True\n\n      pollAttribute proxy attributeName (Milliseconds 2000)\n\n      withSubscribedEvent proxy attributeName ChangeEvent False eventCallback do\n        forM_ [0 .. 2] \\_ -\u003e do\n          putStrLn \"waiting for change\"\n          _ \u003c- readChan chan\n          putStrLn \"received change\"\n#+end_src\n\n*** Example: Web Astor\n\nUnder =benchmark= in the =.cabal= file, you will find =web-astor=, which is a web-based implementation of the Astor starter overlay. It runs on =localhost:8081= and displays a HTML version of Astor, asking for a Tango host. The code is short and should be fairly easy to grasp. A screenshot of that should explain it well:\n\n[[https://raw.githubusercontent.com/pmiddend/hs-tango/main/doc-assets/web-astor.png]]\n\nThe example uses Servant and Lucid to render the HTML.\n** What's missing\n\n- Server: Everything\n- Client\n  + Setting advanced attribute properties, specifically event-related ones like =rel_change= and the period for periodic events. This is no technical difficulty, you just have to write the code.\n  + Commands returning or receiving an =UInt32=. I'm not sure how to handle this, since tango has no such data type.\n  + In event callbacks, it would be good to transport more information like the list of errors, not just a boolean (see cppTango's =event.h=)\n  + Dynamic attribute properties such as the \"quality\" (currently we're only exporting read/write value)\n** Rationale for the used dependencies\n\n- =derive-storable= so that we can just declare data types as records, and have C =Storable= instances generated\n- =text= to replace =String= for textual data (=ByteString= might have been an option, we haven't decided yet)\n- =unliftio= to have the opssibility to have code running in =MonadIO=\n** Interesting links/documentation\n\n- [[https://www.esrf.fr/computing/cs/tango/tango_doc/kernel_doc/cpp_doc/classTango_1_1DeviceProxy.html][DeviceProxy C++ API reference]]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmiddend%2Fhs-tango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmiddend%2Fhs-tango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmiddend%2Fhs-tango/lists"}