ConDB Web Interface


Get data

HTTP GET request URL format:
- Get data for specific time: ..../get?table=<table>&t=<datetime>&columns=<column>,<column>...
- Get data for time range: ..../get?table=<table>&t0=<datetime>&t1=<datetime>&columns=<column>,<column>...

Additional optional arguments:

  • Data type: ...&type=<data type> - default: common data type
  • Tag: ...&tag=<tag>
  • Record time: ...&rtime=<datetime>
  • Channel range: ...&cr=<channel>-<channel>
  • Data filtering: ...&where=<column><op><value>[,...]
    op can be: < <= = >= > !=
    <column><op><value> condition can be repeated, comma separated. Conditions are combined using logical AND
    Example: ...&where=x>0,x<=3
  • Cache control:
    - ...&cache=flush - flush cache for this table
    - ...&cache=no - do not use cache for this request

Datetime format:
ZZ is time zone offset in hours from UTC. Use 00 for UTC time.
- Integer or floating point seconds since Jan 1 1970
- Implied time zone is Central

Data format

"get" request returns data in CSV format. There will be at least 1 row per channel. If the request was for a time range then there may be multiple rows per channel, each row will correspond to the validity interval.
Format of the CSV file:

<channelid>,<validity time>,<data1>,<data2>,...
<channelid>,<validity time>,<data1>,<data2>,...

validity time will be represented as integer time in seconds since Jan1 1970.
Data items will be represented as floating point numbers.
Channel ids are (long) integers.

Put data

HTTP POST request URL format: ..../put?table=<table>
Optional: ...&type=<data type>
- can be repeated for multiple types: ...&type=t1&type=t2
- or comma separated: ...&type=t1,t2,t3
- default - common data type

Data format:

<channelid>,<validity time>,<data1>,<data2>,...
<channelid>,<validity time>,<data1>,<data2>,...

Tolerance row, if present, must be second row (next after the header row), it must have word "tolerance" instead of the channel id, "t" column will be ignored.
Tolerance row is optional. If not present, all tolerances will be assumed to be 0. Tolerances are absolute. They can be either integer or floating point numbers.

If Mask argument is missing, default is 0, which makes the data unusable.


Put request needs to be authenticated. Authentication is done by calculating MD5 signature over 4 components in this order:

  1. Password - secret shared between the client and the server
  2. Salt - arbitrary random string generated by the client for each request
  3. URL query string (the part of URL after the question mark). E.g. for URL "..../put?table=occupancy", it is "table=occupancy"
  4. Body of the request

Once the signature is calculated, its hexadecimal representation and the salt are sent along with the request in extra HTTP request headers:

X-Signature: 0011ef7d1610df972307c2b86178ac3e
X-Salt: 32f6d043d948

Sample Python code to send an authenticated "put data" request:

import hashlib, random, string
import urllib2

# generate CSV file as list of lines

csv = []
# ... populate CSV file here. 
# Make sure lines do include newline characters, 
# so that they are included in the signature

random.seed()   # initialize from time

salt = ''.join(random.choice(string.ascii_letters+string.digits) for x in range(100))  # generate random salt
m = hashlib.md5()
for line in csv:  m.update(line)
signature = m.hexdigest()

request = urllib2.Request("",
    {  "X-Salt": salt,
       "X-Signature": signature })
response = urllib2.urlopen(request)

Create Snapshot

HTTP GET request URL: .../snapshot?table=<table>&t=<validity datetime>
Optional argument: prefill=(yes|no), default is yes. If prefill=yes, new snapshot will be pre-populated with data from current state of the database at specified validity time

Tag data

HTTP GET request URL: ..../tag?table=<table>&tag=<tag>

This will tag current state of the database. Optionally, "&override=yes" can be added. That will remove existing tag "tag" first and then re-tag current state of the database. If override=yes is not specified, and tag with given name already exists, error will be generated.

Another optional argument is copy_from=<existing tag> - if specified, it will create a copy of the existing tag, instead of tagging current state of the database. Override can be used together with copy_from, e.g.: