{"id":17511728,"url":"https://github.com/claws/txcosm","last_synced_at":"2025-03-05T15:30:43.856Z","repository":{"id":6205544,"uuid":"7436461","full_name":"claws/txcosm","owner":"claws","description":"A Python Twisted client implementation of the Cosm v2 API","archived":false,"fork":false,"pushed_at":"2018-03-06T11:35:06.000Z","size":70,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-24T14:13:43.203Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","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/claws.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-04T06:52:45.000Z","updated_at":"2018-03-06T11:35:06.000Z","dependencies_parsed_at":"2022-09-10T19:40:24.035Z","dependency_job_id":null,"html_url":"https://github.com/claws/txcosm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/claws%2Ftxcosm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/claws%2Ftxcosm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/claws%2Ftxcosm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/claws%2Ftxcosm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/claws","download_url":"https://codeload.github.com/claws/txcosm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242052623,"owners_count":20064217,"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":[],"created_at":"2024-10-20T05:09:42.532Z","updated_at":"2025-03-05T15:30:43.353Z","avatar_url":"https://github.com/claws.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# txcosm\n\n## Introduction\ntxcosm is a Python Twisted package implementing the v2 Cosm ([API](https://cosm.com/docs/v2/\u003e). Use txcosm to integrate non blocking access to the Cosm API into your Python Twisted application.\n\n![PyPi version](https://img.shields.io/pypi/v/txcosm.svg) \u0026nbsp;\u0026nbsp; ![PyPi version](https://img.shields.io/pypi/dm/txcosm.svg)\n\n## Background\nCosm was once known as Pachube. This package originated as _txpachube_. It has been renamed to mirror the new site name and development continues in this repository.\n\n## Details\ntxcosm implements the full v2 Cosm API (Feeds, Datastreams, Datapoints, Triggers, Users, Keys) and many of the data structures (Unit, Location, Datapoint, Datastream, Environment, EnvironmentList, Trigger, TriggerList Key, KeyList, User, UserList) contained in requests and responses.\n\nThe data structures support encoding and decoding from JSON/XML formats. These structures are useful when building data to send to Cosm and also for processing Cosm data returned from queries.\n\nThe txcosm client methods take a data string argument that will form the body of the message sent to Cosm. How you generate this body data is up to you. You might choose to manually create the data something like this:\n\n```python\n# manually create feed data message body content\nfeed_data = {\"title\" : \"A Temporary Test Feed\",\n             \"version\" : \"1.0.0\"}\njson_feed_data = json.dumps(feed_data)\n```\n\nHowever, the txcosm package implements many of the data structures used by Cosm requests and responses as Python objects. So the JSON formatted feed data above could also be generated using these txcosm data structure objects like this:\n\n```python\n# Define a dict of valid data structure keywords for use as\n# key word arguments to the data structure initialiser.\nenv_kwargs = {txcosm.DataFields.Title : \"A Temporary Test Feed\",\n              txcosm.DataFields.Version : \"1.0.0\"}\nenvironment = txcosm.Environment(**env_kwargs)\njson_feed_data = environment.encode()\n```\n\nOr in a more compact form once you are familiar with a data structure's valid DataField items:\n\n```python\nenvironment = txcosm.Environment(title=\"A Temporary Test Feed\", version=\"1.0.0\")\njson_feed_data = environment.encode()\n```\n\nRequests to Cosm are automatically timed out after 10 seconds. You can change the timeout value as follows:\n```python\nfrom txcosm.HTTPClient import HTTPClient\nclient = HTTPClient()\nclient.request_timeout = 5.0\n```\nClient functions will return None when a timeout or error is encountered. You should check the returned object for None before assuming that the function call was successful.\nFor example if you were updating a datastream you would call the ```client.update_datapoints``` function and you would then check for None and if None was returned then you should retry the update.\n\nIn addition to the standard HTTP client, txcosm also implements a client that connects to the (Socket Server) PAWS service. This allows long running, persistent, connections to be made to the Cosm service. This type of client is useful for applications which require realtime updates on change of status. Realtime feed updates are available through the subscription feature exposed in the beta PAWS service.\n\n## Dependencies\n\n* Python\n* Twisted\n\n  - zope.interface\n  - pyOpenSSL (used by Twisted for https - in our case for secure access to Cosm)\n\n\n## Install\n\nA number of methods are available to install this package.\n\n* Using pip with PyPI as source:\n\n```bash\n$ [sudo] pip install txcosm\n```\n\n* Using pip with github source:\n\n```bash\n$ [sudo] pip install git+git://github.com/claws/txcosm.git\n```\n\n* Manually download and install the txcosm archive. For other manual download options (zip, tarball) visit the github web page of [txcosm](https://github.com/claws/txcosm):\n\n```bash\n$ git clone git://github.com/claws/txcosm.git\n$ cd txcosm\n$ [sudo] python setup.py install\n```\n\n### Test Installation\n\n```bash\n$ python\n\u003e\u003e\u003e import txcosm\n\u003e\u003e\u003e\n```\n\n## Examples\n\nAll examples require you to have a Cosm account and an appropriately configured (permissions set to create, update, read, delete) Cosm API key.\n\nExample scripts can be found in the examples directory.\n\nBelow are some simple examples to give a quick glimpse of how to use this package.\n\nList Cosm feeds visible to the API key supplied:\n\n```python\n#!/usr/bin/env python\n# This example demonstrates a request for feeds visible to the\n# supplied API key. It initialises the Client object with a\n# default API key that will be used if no api_key argument is\n# passed to the various API methods.\n# Parameters can be passed to customise the default results.\n# In this case only 'live' feeds and 'summary' content is\n# being requested.\n\nfrom twisted.internet import reactor, defer\nfrom txcosm.HTTPClient import HTTPClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n@defer.inlineCallbacks\ndef demo():\n    client = HTTPClient(api_key=API_KEY)\n    feed_list = yield client.list_feeds(parameters={'status' : 'live', 'content' : 'summary'})\n    if feed_list:\n        print \"Received feed list content:\\n%s\\n\" % feed_list\n    else:\n        print \"Error listing visible feeds\"\n    reactor.callLater(0.1, reactor.stop)\n    defer.returnValue(True)\n\nif __name__ == \"__main__\":\n    reactor.callWhenRunning(demo)\n    reactor.run()\n```\n\nCreate a new feed:\n\n```python\n#!/usr/bin/env python\n# This example demonstrates the ability to create new feeds. It also\n# shows an API key being passed to the create_feed method directly\n# as no default key was passed to the Client object initialiser.\n# No format needs to be specified because json is the default format\n# used.\n\nfrom twisted.internet import reactor, defer\nimport txcosm\nfrom txcosm.HTTPClient import HTTPClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n@defer.inlineCallbacks\ndef demo():\n    client = HTTPClient()\n    environment = txcosm.Environment(title=\"A Temporary Test Feed\", version=\"1.0.0\")\n    new_feed_id = yield client.create_feed(api_key=API_KEY, data=environment.encode())\n    if new_feed_id:\n        print \"Created new feed with id: %s\" % new_feed_id\n    else:\n        print \"Error creating new feed\"\n    reactor.callLater(0.1, reactor.stop)\n    defer.returnValue(True)\n\n\nif __name__ == \"__main__\":\n    reactor.callWhenRunning(demo)\n    reactor.run()\n```\n\nUpdate a feed:\n\n```python\n#!/usr/bin/env python\n# This example show how a feed can be updated using your own generated\n# data, in this case XML data.\n# The Client object has been initialised with an API key and a feed id\n# so they don't need to be passed to the update_feed method. The format\n# argument is JSON by default so it must be explicitly set as this\n# example is using XML.\n\nfrom twisted.internet import reactor\nimport txcosm\nfrom txcosm.HTTPClient import HTTPClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n# Paste you feed identifier here\nFEED_ID = \"\"\n\n# example feed update data\nfeed_data = \"\"\"\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003ceeml xmlns=\"http://www.eeml.org/xsd/0.5.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"0.5.1\" xsi:schemaLocation=\"http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd\"\u003e\n  \u003cenvironment\u003e\n    \u003ctitle\u003ebridge19\u003c/title\u003e\n    \u003cstatus\u003elive\u003c/status\u003e\n    \u003cdescription\u003ebridge environment 19\u003c/description\u003e\n    \u003ctag\u003eTag1\u003c/tag\u003e\n    \u003ctag\u003eTag2\u003c/tag\u003e\n    \u003cdata id=\"3\"\u003e\n      \u003ccurrent_value\u003e-312\u003c/current_value\u003e\n      \u003cmax_value\u003e999.0\u003c/max_value\u003e\n      \u003cmin_value\u003e7.0\u003c/min_value\u003e\n    \u003c/data\u003e\n    \u003cdata id=\"0\"\u003e\n      \u003ccurrent_value\u003e11\u003c/current_value\u003e\n      \u003cmax_value\u003e211.0\u003c/max_value\u003e\n      \u003cmin_value\u003e7.0\u003c/min_value\u003e\n    \u003c/data\u003e\n    \u003cdata id=\"4\"\u003e\n      \u003ccurrent_value\u003e-3332\u003c/current_value\u003e\n    \u003c/data\u003e\n  \u003c/environment\u003e\n\u003c/eeml\u003e\"\"\"\n\n@defer.inlineCallbacks\ndef demo():\n    client = HTTPClient(api_key=API_KEY, feed_id=FEED_ID)\n    result = client.update_feed(format=txcosm.DataFormats.XML, data=feed_data)\n    if result:\n        print \"Feed updated\"\n    else:\n        print \"Error updating feed\"\n    reactor.callLater(0.1, reactor.stop)\n    defer.returnValue(True)\n\n\nif __name__ == \"__main__\":\n    reactor.callWhenRunning(demo)\n    reactor.run()\n```\n\nRead a feed:\n\n```python\n#!/usr/bin/env python\n# This example demonstrates a request for feed data and uses\n# additional parameters to restrict the datastreams returned.\n# It initialises the Client object with a default API key and\n# feed id so they do not need to be passed to the read_feed\n# method.\n\nfrom twisted.internet import reactor, defer\nfrom txcosm.HTTPClient import HTTPClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n# Paste the feed identifier you wish to be read here\nFEED_ID = \"\"\n\n@defer.inlineCallbacks\ndef demo():\n    client = HTTPClient(api_key=API_KEY, feed_id=FEED_ID)\n    feed = yield client.read_feed(parameters={'datastream':'temperature'})\n    if feed:\n        print \"Received feed content:\\n%s\\n\" % feed\n    else:\n        print \"Error reading feed\"\n    reactor.callLater(0.1, reactor.stop)\n    defer.returnValue(True)\n\nif __name__ == \"__main__\":\n    reactor.callWhenRunning(demo)\n    reactor.run()\n```\n\nDelete a feed:\n\n```python\n#!/usr/bin/env python\n# This example demonstrates the ability to delete a feed.\n#\n# WARNING: This will REALLY delete the feed identifier listed. Make sure it is only a test feed.\n#\n\nfrom twisted.internet import reactor, defer\nfrom txcosm.HTTPClient import HTTPClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n# Paste the feed identifier you wish to be DELETED here\nFEED_ID = \"\"\n\n@defer.inlineCallbacks\ndef demo():\n    client = HTTPClient()\n    feed_delete_status = yield client.delete_feed(api_key=API_KEY, feed_id=FEED_ID)\n    if feed_delete_status:\n        print \"Deleted feed: %s\" % feed_delete_status\n    else:\n        print \"Error deleting feed: %s\" % str(ex)\n    reactor.callLater(0.1, reactor.stop)\n    defer.returnValue(True)\n\n\nif __name__ == \"__main__\":\n    reactor.callWhenRunning(demo)\n    reactor.run()\n```\n\n\nUse the PAWS API to subscribe to a feed or datastream and receive updates whenever the feed/datastream value changes:\n\n```python\n#!/usr/bin/env python\n\nfrom twisted.internet import reactor\nimport txcosm\nfrom txcosm.PAWSClient import PAWSClient\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n# Paste the feed identifier you wish to monitor here\nFEED_ID = \"\"\n\n# Paste a datastream identifier from the feed here if you only want to\n# monitor a particular datastream instead of the whole feed.\nDATASTREAM_ID = \"\"\n\n#\n# Set up callback handlers\n#\n\ndef updateHandler(dataStructure):\n    \"\"\"\n    Handle a txcosm data structure object generated as a result of a\n    subscription update message received from Cosm.\n    The data structure returned will vary depending on the resource subscribed to.\n    If a datastream is specified the returned data structure will be a txcosm.Datastream\n    object. If just a feed is specified then the returned data structure will be a\n    txcosm.Environment object.\n    \"\"\"\n    print \"Subscription update message received:\\n%s\\n\" % str(dataStructure)\n\n\ndef do_subscribe(connected, client, resource):\n    \"\"\" Subscribe to the specified resource if the connection is established \"\"\"\n    if connected:\n        print \"Connected to PAWS service\"\n\n        def handleSubscribeResponse(status):\n            print \"Subscribe response status: %s\" % status\n\n        print \"Subscribing for updates to: %s\" % resource\n        token, d = client.subscribe(resource, updateHandler)\n        print \"Subscription token is: %s\" % token\n        d.addCallback(handleSubscribeResponse)\n    else:\n        print \"Connection failed\"\n        reactor.callLater(0.1, reactor.stop)\n        return\n\n\nif __name__ == '__main__':\n    if DATASTREAM_ID:\n        resource = \"/feeds/%s/datastreams/%s\" % (FEED_ID, DATASTREAM_ID)\n    else:\n        resource = \"/feeds/%s\" % (FEED_ID)\n\n    client = PAWSClient(api_key=API_KEY)\n    d = client.connect()\n    d.addCallback(do_subscribe, client, resource)\n    reactor.run()\n```\n\nExample use case scenario:\n```python\n#!/usr/bin/env python\n\n# This example demonstrates how you could use the txcosm module to\n# help upload sensor data (in this scenario a CurrentCost device) to\n# Cosm.\n# A txcosm.Environment data structure is generated and populated\n# with current value data. All the implemented data structures\n# support encoding to JSON (default) and XML (EEML).\n#\n# In this example the CurrentCost sensor object is derived from the\n# separate txcurrentcost package. A shameless plug for my txcurrentcost\n# package no doubt, but this is why I wrote txcosm. If you want to run this script\n# you would need to install that package.\n#\n\nfrom twisted.internet import reactor\nimport txcosm\nfrom txcosm.HTTPClient import HTTPClient\nimport txcurrentcost.monitor\n\n# Paste your Cosm API key here\nAPI_KEY = \"\"\n\n# Paste the feed identifier you wish to use here\nFEED_ID = \"\"\n\nCurrentCostMonitorConfigFile = \"/path/to/your/config/file\"\n\n\nclass MyCurrentCostMonitor(txcurrentcost.monitor.Monitor):\n    \"\"\"\n    Extends the txcurrentCost.monitor.Monitor by implementing periodic update\n    handler to call a supplied data handler.\n    \"\"\"\n\n    def __init__(self, config_file, periodicUpdateDataHandler):\n        super(MyCurrentCostMonitor, self).__init__(config_file)\n        self.periodicUpdateDataHandler = periodicUpdateDataHandler\n\n    def periodicUpdateReceived(self, timestamp, temperature, sensor_type, sensor_instance, sensor_data):\n        if sensor_type == txcurrentcost.Sensors.ElectricitySensor:\n            if sensor_instance == txcurrentcost.Sensors.WholeHouseSensorId:\n                self.periodicUpdateDataHandler(timestamp, temperature, sensor_data)\n\n\nclass Monitor(object):\n\n    def __init__(self, config):\n        self.temperature_datastream_id = \"temperature\"\n        self.energy_datastream_id = \"energy\"\n        self.cosmClient = HTTPClient(api_key=API_KEY, feed_id=FEED_ID)\n        currentCostMonitorConfig = txcurrentcost.monitor.MonitorConfig(CurrentCostMonitorConfigFile)\n        self.sensor = txcurrentcost.monior.Monitor(currentCostMonitorConfig,\n                                                   self.handleCurrentCostPeriodicUpdateData)\n\n    def start(self):\n        \"\"\" Start sensor \"\"\"\n        self.sensor.start()\n\n    def stop(self):\n        \"\"\" Stop the sensor \"\"\"\n        self.sensor.stop()\n\n    def def handleCurrentCostPeriodicUpdateData(self, timestamp, temperature, watts_on_channels):\n        \"\"\" Handle latest sensor periodic update \"\"\"\n\n        # Populate a txcosm.Environment data structure object with latest data\n\n        environment = txcosm.Environment(version=\"1.0.0\")\n        environment.setCurrentValue(self.temperature_datastream_id, \"%.1f\" % temperature)\n        environment.setCurrentValue(self.energy_datastream_id, str(watts_on_channels[0]))\n\n        # Update the Cosm service with latest value(s)\n        d = self.cosmClient.update_feed(data=environment.encode())\n        d.addCallback(lambda result: print \"Cosm updated\")\n        d.addErrback(lambda reason: print \"Cosm update failed: %s\" % str(reason))\n\n\nif __name__ == \"__main__\":\n    monitor = Monitor()\n    reactor.callWhenRunning(monitor.start)\n    reactor.run()\n```\n\n\n[![Analytics](https://ga-beacon.appspot.com/UA-29867375-2/txcosm/readme?pixel)](https://github.com/claws/txcosm)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclaws%2Ftxcosm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclaws%2Ftxcosm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclaws%2Ftxcosm/lists"}