diff --git a/app/dmfs.f90 b/app/dmfs.f90 index ba751b4..d927e2a 100644 --- a/app/dmfs.f90 +++ b/app/dmfs.f90 @@ -214,11 +214,12 @@ integer function read_config(app) result(rc) call dm_config_close(config) end function read_config - integer function read_observ(observ, node_id, sensor_id, debug) result(rc) + integer function read_observ(observ, node_id, sensor_id, source, debug) result(rc) !! Reads observation from file. type(observ_type), target, intent(inout) :: observ !! Observation to read. character(len=*), intent(in) :: node_id !! Node id of observation. character(len=*), intent(in) :: sensor_id !! Sensor id of observation. + character(len=*), intent(in) :: source !! Source of observation. logical, intent(in), optional :: debug !! Output debug messages. integer :: delay @@ -235,6 +236,7 @@ integer function read_observ(observ, node_id, sensor_id, debug) result(rc) observ%id = dm_uuid4() observ%node_id = node_id observ%sensor_id = sensor_id + observ%source = source observ%timestamp = dm_time_now() if (observ%nrequests == 0) then @@ -389,7 +391,7 @@ subroutine run(app) end if ! Read observation from file system. - rc = read_observ(observ, app%node, app%sensor, debug=debug) + rc = read_observ(observ, app%node, app%sensor, app%name, debug=debug) if (debug) then call dm_log(LOG_DEBUG, 'finished observ ' // trim(observ%name) // & diff --git a/app/dmpipe.f90 b/app/dmpipe.f90 index b151ae7..ac7e858 100644 --- a/app/dmpipe.f90 +++ b/app/dmpipe.f90 @@ -281,6 +281,7 @@ subroutine run(app) observ%id = dm_uuid4() observ%node_id = app%node observ%sensor_id = app%sensor + observ%source = app%name observ%timestamp = dm_time_now() if (observ%nrequests == 0) then diff --git a/app/dmserial.f90 b/app/dmserial.f90 index 34bcb02..3ea4fce 100644 --- a/app/dmserial.f90 +++ b/app/dmserial.f90 @@ -495,6 +495,7 @@ integer function run(app, tty) result(rc) ! Initialise observation. observ%node_id = app%node observ%sensor_id = app%sensor + observ%source = app%name observ%path = trim(app%tty) if (debug) then diff --git a/app/dmsync.f90 b/app/dmsync.f90 index cd21f5a..7064e8e 100644 --- a/app/dmsync.f90 +++ b/app/dmsync.f90 @@ -482,9 +482,9 @@ integer function run(app, db, sem) result(rc) end select code_select ! Update sync data. - syncs(i)%timestamp = dm_time_now() ! Time of sync attempt. - syncs(i)%code = responses(i)%code ! Server status code. - syncs(i)%nattempts = syncs(i)%nattempts + 1 ! Number of sync attempts. + syncs(i)%timestamp = dm_time_now() ! Time of sync attempt. + syncs(i)%code = responses(i)%code ! Server status code. + syncs(i)%attempts = syncs(i)%attempts + 1 ! Number of sync attempts. ! Insert or replace the sync data in database. If the database ! is busy, try up to `APP_DB_NATTEMPTS` times, then abort. diff --git a/config/dmfs.conf.sample b/config/dmfs.conf.sample index 93241bb..b369d81 100644 --- a/config/dmfs.conf.sample +++ b/config/dmfs.conf.sample @@ -33,7 +33,7 @@ observs = { { name = "dummy-observ", target_id = "dummy-target", - receivers = { "dmfs", "dmdb" }, + receivers = { "dmdb" }, requests = { { request = path, diff --git a/config/dmpipe.conf.sample b/config/dmpipe.conf.sample index 6be3f85..22af0ab 100644 --- a/config/dmpipe.conf.sample +++ b/config/dmpipe.conf.sample @@ -26,7 +26,7 @@ observ = { name = "dummy-observ", target_id = "dummy-target", - receivers = { "dmpipe", "dmrecv" }, + receivers = { "dmrecv" }, requests = { -- -- Read CPU temperature. diff --git a/config/dmserial.conf.sample b/config/dmserial.conf.sample index 9527e36..dcc73bd 100644 --- a/config/dmserial.conf.sample +++ b/config/dmserial.conf.sample @@ -71,7 +71,7 @@ observs = { -- name = "meter", target_id = "meter", - receivers = { "dmserial", "dmdb" }, + receivers = { "dmdb" }, requests = { { request = "Meter" .. del, diff --git a/guide/guide.adoc b/guide/guide.adoc index fa0913e..c5ab197 100644 --- a/guide/guide.adoc +++ b/guide/guide.adoc @@ -3760,6 +3760,7 @@ NODE%Z=0.0, | `sensor_id` | string | 32 | Sensor id (`-0-9A-Za-z`). | `target_id` | string | 32 | Target id (`-0-9A-Za-z`). | `name` | string | 32 | Observation name (`-0-9A-Za-z`). +| `source` | string | 32 | Observation source (`-0-9A-Za-z`). | `timestamp` | string | 32 | Date and time of observation (ISO 8601). | `path` | string | 32 | Path of TTY/PTY device. | `priority` | integer | 4 | Message queue priority (>= 0). @@ -3827,73 +3828,74 @@ NODE%Z=0.0, | 3 | `sensor_id` | Sensor id. | 4 | `target_id` | Target id. | 5 | `name` | Observation name. -| 6 | `timestamp` | Date and time of observation. -| 7 | `path` | Path of TTY/PTY device. -| 8 | `priority` | Message queue priority. -| 9 | `error` | Error code. -| 10 | `next` | Cursor of receiver list (0 to 16). -| 11 | `nreceivers` | Number of receivers (0 to 16). -| 12 | `nrequests` | Number of sensor requests (0 to 8). -| 13 – 28 | `receivers` | Array of receiver names (16). -| 13 | `receiver` | Receiver 1. -| 14 | `receiver` | Receiver 2. -| 15 | `receiver` | Receiver 3. -| 16 | `receiver` | Receiver 4. -| 17 | `receiver` | Receiver 5. -| 18 | `receiver` | Receiver 6. -| 19 | `receiver` | Receiver 7. -| 20 | `receiver` | Receiver 8. -| 21 | `receiver` | Receiver 9. -| 22 | `receiver` | Receiver 10. -| 23 | `receiver` | Receiver 11. -| 24 | `receiver` | Receiver 12. -| 25 | `receiver` | Receiver 13. -| 26 | `receiver` | Receiver 14. -| 27 | `receiver` | Receiver 15. -| 28 | `receiver` | Receiver 16. -| 29 – 764 | `requests` | Array of requests (8). -| 29 – 103 | `request` | Request 1. -| 29 | `timestamp` | Date and time of request. -| 30 | `request` | Raw request to sensor. -| 31 | `response` | Raw response of sensor. -| 32 | `delimiter` | Request delimiter. -| 33 | `pattern` | Regular expression pattern that describes the raw response. -| 34 | `delay` | Delay in mseconds to wait after the request. -| 35 | `error` | Error code. -| 36 | `mode` | Request mode. -| 37 | `retries` | Number of retries performed. -| 38 | `state` | Request state. -| 39 | `timeout` | Request timeout in mseconds. -| 40 | `nresponses` | Number of responses (0 to 16). -| 41 – 120 | `responses` | Array of responses (16). -| 41 – 45 | `response` | Response 1. -| 41 | `name` | Response name. -| 42 | `unit` | Response unit. -| 43 | `type` | Response value type. -| 44 | `error` | Response error. -| 45 | `value` | Response value. -| 46 – 50 | `response` | Response 2. -| 51 – 55 | `response` | Response 3. -| 56 – 60 | `response` | Response 4. -| 61 – 65 | `response` | Response 5. -| 66 – 70 | `response` | Response 6. -| 71 – 75 | `response` | Response 7. -| 76 – 80 | `response` | Response 8. -| 81 – 85 | `response` | Response 9. -| 86 – 90 | `response` | Response 10. -| 91 – 95 | `response` | Response 11. -| 96 – 100 | `response` | Response 12. -| 101 – 105 | `response` | Response 13. -| 106 – 110 | `response` | Response 14. -| 111 – 115 | `response` | Response 15. -| 116 – 120 | `response` | Response 16. -| 121 – 212 | `request` | Request 2. -| 213 – 304 | `request` | Request 3. -| 305 – 396 | `request` | Request 4. -| 397 – 488 | `request` | Request 5. -| 489 – 580 | `request` | Request 6. -| 581 – 672 | `request` | Request 7. -| 673 – 764 | `request` | Request 8. +| 6 | `source` | Observation source. +| 7 | `timestamp` | Date and time of observation. +| 8 | `path` | Path of TTY/PTY device. +| 9 | `priority` | Message queue priority. +| 10 | `error` | Error code. +| 11 | `next` | Cursor of receiver list (0 to 16). +| 12 | `nreceivers` | Number of receivers (0 to 16). +| 13 | `nrequests` | Number of sensor requests (0 to 8). +| 14 – 29 | `receivers` | Array of receiver names (16). +| 14 | `receiver` | Receiver 1. +| 15 | `receiver` | Receiver 2. +| 16 | `receiver` | Receiver 3. +| 17 | `receiver` | Receiver 4. +| 18 | `receiver` | Receiver 5. +| 19 | `receiver` | Receiver 6. +| 20 | `receiver` | Receiver 7. +| 21 | `receiver` | Receiver 8. +| 22 | `receiver` | Receiver 9. +| 23 | `receiver` | Receiver 10. +| 24 | `receiver` | Receiver 11. +| 25 | `receiver` | Receiver 12. +| 26 | `receiver` | Receiver 13. +| 27 | `receiver` | Receiver 14. +| 28 | `receiver` | Receiver 15. +| 29 | `receiver` | Receiver 16. +| 30 – 765 | `requests` | Array of requests (8). +| 30 – 104 | `request` | Request 1. +| 30 | `timestamp` | Date and time of request. +| 31 | `request` | Raw request to sensor. +| 32 | `response` | Raw response of sensor. +| 33 | `delimiter` | Request delimiter. +| 34 | `pattern` | Regular expression pattern that describes the raw response. +| 35 | `delay` | Delay in mseconds to wait after the request. +| 36 | `error` | Error code. +| 37 | `mode` | Request mode. +| 38 | `retries` | Number of retries performed. +| 39 | `state` | Request state. +| 40 | `timeout` | Request timeout in mseconds. +| 41 | `nresponses` | Number of responses (0 to 16). +| 42 – 121 | `responses` | Array of responses (16). +| 42 – 46 | `response` | Response 1. +| 42 | `name` | Response name. +| 43 | `unit` | Response unit. +| 44 | `type` | Response value type. +| 45 | `error` | Response error. +| 46 | `value` | Response value. +| 47 – 51 | `response` | Response 2. +| 52 – 56 | `response` | Response 3. +| 57 – 61 | `response` | Response 4. +| 62 – 66 | `response` | Response 5. +| 67 – 71 | `response` | Response 6. +| 72 – 76 | `response` | Response 7. +| 77 – 81 | `response` | Response 8. +| 82 – 86 | `response` | Response 9. +| 87 – 91 | `response` | Response 10. +| 92 – 96 | `response` | Response 11. +| 97 – 101 | `response` | Response 12. +| 102 – 106 | `response` | Response 13. +| 107 – 111 | `response` | Response 14. +| 112 – 116 | `response` | Response 15. +| 117 – 121 | `response` | Response 16. +| 122 – 213 | `request` | Request 2. +| 214 – 305 | `request` | Request 3. +| 306 – 397 | `request` | Request 4. +| 398 – 489 | `request` | Request 5. +| 490 – 581 | `request` | Request 6. +| 582 – 673 | `request` | Request 7. +| 674 – 765 | `request` | Request 8. |=== .HDF5 [[data-observ-hdf5]] @@ -3908,6 +3910,7 @@ The HDF5 data-set description is too large to be fully shown in this document. "sensor_id": "dummy-sensor", "target_id": "dummy-target", "name": "dummy-observ", + "source": "dmdummy", "timestamp": "1970-01-01T00:00:00.000000+00:00", "path": "/dev/null", "priority": 0, @@ -3955,9 +3958,10 @@ The HDF5 data-set description is too large to be fully shown in this document. node_id = "dummy-node", sensor_id = "dummy-sensor", target_id = "dummy-target", + name = "dummy-observ", + source = "dmdummy", timestamp = "1970-01-01T00:00:00.000000+00:00", path = "/dev/null", - name = "dummy-observ", error = 0, next = 1, priority = 0, @@ -4000,6 +4004,7 @@ OBSERV%NODE_ID="dummy-node", OBSERV%SENSOR_ID="dummy-sensor", OBSERV%TARGET_ID="dummy-target", OBSERV%NAME="dummy-observ", +OBSERV%SOURCE="dmdummy", OBSERV%TIMESTAMP="1970-01-01T00:00:00.000000+00:00", OBSERV%PATH="/dev/null", OBSERV%PRIORITY=0, diff --git a/guide/resources/images/observ.svg b/guide/resources/images/observ.svg index e5ac203..75f0078 100644 --- a/guide/resources/images/observ.svg +++ b/guide/resources/images/observ.svg @@ -1 +1 @@ -nodesnode_id : INTEGERid : TEXTname : TEXTmeta : TEXTx : REALy : REALz : REALidx_nodes_id (id)sqlite_autoindex_nodes_1 (id)observsobserv_id : INTEGERnode_id : INTEGERsensor_id : INTEGERtarget_id : INTEGERid : TEXTname : TEXTtimestamp : TEXTpath : TEXTpriority : INTEGERerror : INTEGERnext : INTEGERnreceivers : INTEGERnrequests : INTEGERidx_observs_timestamp (timestamp)idx_observs (timestamp, name, error)sqlite_autoindex_observs_1 (id)receiversreceiver_id : INTEGERobserv_id : INTEGERidx : INTEGERname : TEXTidx_receivers_idx (idx)sqlite_autoindex_receivers_1 (observ_id, idx)requestsrequest_id : INTEGERobserv_id : INTEGERidx : INTEGERrequest : TEXTresponse : TEXTdelimiter : TEXTpattern : TEXTtimestamp : TEXTdelay : INTEGERerror : INTEGERmode : INTEGERretries : INTEGERstate : INTEGERtimeout : INTEGERnresponses : INTEGERidx_requests_timestamp (timestamp)idx_requests_idx (idx)sqlite_autoindex_requests_1 (observ_id, idx)responsesresponse_id : INTEGERrequest_id : INTEGERidx : INTEGERname : TEXTunit : TEXTtype : INTEGERerror : INTEGERvalue : REALidx_responses_name (name)idx_responses_request_id (request_id)idx_responses (request_id, idx, name, unit, type, error, value)sqlite_autoindex_responses_1 (request_id, idx)sensorssensor_id : INTEGERnode_id : INTEGERid : TEXTtype : INTEGERname : TEXTsn : TEXTmeta : TEXTx : REALy : REALz : REALidx_sensors_id (id)sqlite_autoindex_sensors_1 (id)sync_nodessync_node_id : INTEGERnode_id : INTEGERtimestamp : TEXTcode : INTEGERnattempts : INTEGERsqlite_autoindex_sync_nodes_1 (node_id)sync_observssync_observ_id : INTEGERobserv_id : INTEGERtimestamp : TEXTcode : INTEGERnattempts : INTEGERsqlite_autoindex_sync_observs_1 (observ_id)sync_sensorssync_sensor_id : INTEGERsensor_id : INTEGERtimestamp : TEXTcode : INTEGERnattempts : INTEGERsqlite_autoindex_sync_sensors_1 (sensor_id)sync_targetssync_target_id : INTEGERtarget_id : INTEGERtimestamp : TEXTcode : INTEGERnattempts : INTEGERsqlite_autoindex_sync_targets_1 (target_id)targetstarget_id : INTEGERid : TEXTname : TEXTmeta : TEXTstate : INTEGERx : REALy : REALz : REALidx_targets_id (id)sqlite_autoindex_targets_1 (id) \ No newline at end of file +nodesnode_id : INTEGERid : TEXTname : TEXTmeta : TEXTx : REALy : REALz : REALidx_nodes_id (id)sqlite_autoindex_nodes_1 (id)observsobserv_id : INTEGERnode_id : INTEGERsensor_id : INTEGERtarget_id : INTEGERid : TEXTname : TEXTsource : TEXTtimestamp : TEXTpath : TEXTpriority : INTEGERerror : INTEGERnext : INTEGERnreceivers : INTEGERnrequests : INTEGERidx_observs_timestamp (timestamp)idx_observs (timestamp, name, error)sqlite_autoindex_observs_1 (id)receiversreceiver_id : INTEGERobserv_id : INTEGERidx : INTEGERname : TEXTidx_receivers_idx (idx)sqlite_autoindex_receivers_1 (observ_id, idx)requestsrequest_id : INTEGERobserv_id : INTEGERidx : INTEGERrequest : TEXTresponse : TEXTdelimiter : TEXTpattern : TEXTtimestamp : TEXTdelay : INTEGERerror : INTEGERmode : INTEGERretries : INTEGERstate : INTEGERtimeout : INTEGERnresponses : INTEGERidx_requests_timestamp (timestamp)idx_requests_idx (idx)sqlite_autoindex_requests_1 (observ_id, idx)responsesresponse_id : INTEGERrequest_id : INTEGERidx : INTEGERname : TEXTunit : TEXTtype : INTEGERerror : INTEGERvalue : REALidx_responses_name (name)idx_responses_request_id (request_id)idx_responses (request_id, idx, name, unit, type, error, value)sqlite_autoindex_responses_1 (request_id, idx)sensorssensor_id : INTEGERnode_id : INTEGERid : TEXTtype : INTEGERname : TEXTsn : TEXTmeta : TEXTx : REALy : REALz : REALidx_sensors_id (id)sqlite_autoindex_sensors_1 (id)sync_nodessync_node_id : INTEGERnode_id : INTEGERtimestamp : TEXTcode : INTEGERattempts : INTEGERsqlite_autoindex_sync_nodes_1 (node_id)sync_observssync_observ_id : INTEGERobserv_id : INTEGERtimestamp : TEXTcode : INTEGERattempts : INTEGERsqlite_autoindex_sync_observs_1 (observ_id)sync_sensorssync_sensor_id : INTEGERsensor_id : INTEGERtimestamp : TEXTcode : INTEGERattempts : INTEGERsqlite_autoindex_sync_sensors_1 (sensor_id)sync_targetssync_target_id : INTEGERtarget_id : INTEGERtimestamp : TEXTcode : INTEGERattempts : INTEGERsqlite_autoindex_sync_targets_1 (target_id)targetstarget_id : INTEGERid : TEXTname : TEXTmeta : TEXTstate : INTEGERx : REALy : REALz : REALidx_targets_id (id)sqlite_autoindex_targets_1 (id) \ No newline at end of file diff --git a/src/dm_csv.f90 b/src/dm_csv.f90 index 6f720a1..98cab53 100644 --- a/src/dm_csv.f90 +++ b/src/dm_csv.f90 @@ -228,6 +228,7 @@ function dm_csv_header_observ(separator) result(header) 'sensor_id' // s // & 'target_id' // s // & 'name' // s // & + 'source' // s // & 'timestamp' // s // & 'tty' // s // & 'priority' // s // & @@ -553,6 +554,7 @@ function csv_from_observ(observ, separator) result(csv) trim(observ%sensor_id) // s // & trim(observ%target_id) // s // & trim(observ%name) // s // & + trim(observ%source) // s // & trim(observ%timestamp) // s // & trim(observ%path) // s // & dm_itoa(observ%priority) // s // & @@ -1084,6 +1086,7 @@ integer function csv_read_observ(observ, unit, separator, quote) result(rc) rc = csv_next(buffer, observ%sensor_id, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, observ%target_id, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, observ%name, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, observ%source, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, observ%timestamp, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, observ%path, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, observ%priority, s, n, p, q); if (rc /= E_NONE) return @@ -1537,12 +1540,13 @@ integer function csv_write_observ(observ, unit, header, separator) result(rc) if (stat /= 0) return end if - write (unit_, '(14a, 4(i0, a), i0)', advance='no', iostat=stat) & + write (unit_, '(16a, 4(i0, a), i0)', advance='no', iostat=stat) & trim(observ%id), s, & trim(observ%node_id), s, & trim(observ%sensor_id), s, & trim(observ%target_id), s, & trim(observ%name), s, & + trim(observ%source), s, & trim(observ%timestamp), s, & trim(observ%path), s, & observ%priority, s, & diff --git a/src/dm_db.f90 b/src/dm_db.f90 index 77ba229..e44d6ad 100644 --- a/src/dm_db.f90 +++ b/src/dm_db.f90 @@ -1605,13 +1605,14 @@ integer function dm_db_insert_observ(db, observ, db_stmt) result(rc) if (sqlite3_bind_text(stmt, 3, trim(observ%sensor_id)) /= SQLITE_OK) exit sql_block if (sqlite3_bind_text(stmt, 4, trim(observ%target_id)) /= SQLITE_OK) exit sql_block if (sqlite3_bind_text(stmt, 5, trim(observ%name)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text(stmt, 6, trim(observ%timestamp)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text(stmt, 7, trim(observ%path)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 8, observ%priority) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 9, observ%error) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 10, observ%next) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 11, observ%nreceivers) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 12, observ%nrequests) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text(stmt, 6, trim(observ%source)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text(stmt, 7, trim(observ%timestamp)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text(stmt, 8, trim(observ%path)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 9, observ%priority) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 10, observ%error) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 11, observ%next) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 12, observ%nreceivers) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 13, observ%nrequests) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -4954,7 +4955,7 @@ integer function db_insert_sync(db, sync, query) result(rc) if (sqlite3_bind_text(stmt, 1, trim(sync%id)) /= SQLITE_OK) exit sql_block if (sqlite3_bind_text(stmt, 2, trim(sync%timestamp)) /= SQLITE_OK) exit sql_block if (sqlite3_bind_int (stmt, 3, sync%code) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 4, sync%nattempts) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 4, sync%attempts) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -5118,11 +5119,12 @@ integer function db_next_row_observ(stmt, observ, validate) result(rc) if (sqlite3_column_type(stmt, 4) /= SQLITE_TEXT) return if (sqlite3_column_type(stmt, 5) /= SQLITE_TEXT) return if (sqlite3_column_type(stmt, 6) /= SQLITE_TEXT) return - if (sqlite3_column_type(stmt, 7) /= SQLITE_INTEGER) return + if (sqlite3_column_type(stmt, 7) /= SQLITE_TEXT) return if (sqlite3_column_type(stmt, 8) /= SQLITE_INTEGER) return if (sqlite3_column_type(stmt, 9) /= SQLITE_INTEGER) return if (sqlite3_column_type(stmt, 10) /= SQLITE_INTEGER) return if (sqlite3_column_type(stmt, 11) /= SQLITE_INTEGER) return + if (sqlite3_column_type(stmt, 12) /= SQLITE_INTEGER) return end if observ%id = sqlite3_column_text(stmt, 0) @@ -5130,13 +5132,14 @@ integer function db_next_row_observ(stmt, observ, validate) result(rc) observ%sensor_id = sqlite3_column_text(stmt, 2) observ%target_id = sqlite3_column_text(stmt, 3) observ%name = sqlite3_column_text(stmt, 4) - observ%timestamp = sqlite3_column_text(stmt, 5) - observ%path = sqlite3_column_text(stmt, 6) - observ%priority = sqlite3_column_int (stmt, 7) - observ%error = sqlite3_column_int (stmt, 8) - observ%next = sqlite3_column_int (stmt, 9) - observ%nreceivers = sqlite3_column_int (stmt, 10) - observ%nrequests = sqlite3_column_int (stmt, 11) + observ%source = sqlite3_column_text(stmt, 5) + observ%timestamp = sqlite3_column_text(stmt, 6) + observ%path = sqlite3_column_text(stmt, 7) + observ%priority = sqlite3_column_int (stmt, 8) + observ%error = sqlite3_column_int (stmt, 9) + observ%next = sqlite3_column_int (stmt, 10) + observ%nreceivers = sqlite3_column_int (stmt, 11) + observ%nrequests = sqlite3_column_int (stmt, 12) rc = E_NONE end function db_next_row_observ @@ -5272,9 +5275,9 @@ integer function db_next_row_sync(stmt, sync) result(rc) end if if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) then - sync%nattempts = sqlite3_column_int(stmt, 3) + sync%attempts = sqlite3_column_int(stmt, 3) else - sync%nattempts = 0 + sync%attempts = 0 end if rc = E_NONE diff --git a/src/dm_geocom_api.f90 b/src/dm_geocom_api.f90 index 659e69e..47e09b9 100644 --- a/src/dm_geocom_api.f90 +++ b/src/dm_geocom_api.f90 @@ -552,7 +552,8 @@ module dm_geocom_api ! PUBLIC GEOCOM PARAMETER FUNCTIONS. ! ************************************************************************** pure elemental integer function dm_geocom_api_parameter_aut_adjmode(param) result(n) - !! Returns `param` or `GEOCOM_AUT_NORM_MODE` if argument is invalid. + !! Parameterisation function for enumeration `AUT_ADJMODE`. Returns + !! `param` or `GEOCOM_AUT_NORM_MODE` if argument is invalid. integer, intent(in) :: param !! `AUT_ADJMODE`. select case (param) @@ -566,7 +567,8 @@ pure elemental integer function dm_geocom_api_parameter_aut_adjmode(param) resul end function dm_geocom_api_parameter_aut_adjmode pure elemental integer function dm_geocom_api_parameter_aut_atrmode(param) result(n) - !! Returns `param` or `GEOCOM_AUT_POSITION` if argument is invalid. + !! Parameterisation function for enumeration `AUT_ATRMODE`. Returns + !! `param` or `GEOCOM_AUT_POSITION` if argument is invalid. integer, intent(in) :: param !! `AUT_ATRMODE`. select case (param) @@ -579,7 +581,8 @@ pure elemental integer function dm_geocom_api_parameter_aut_atrmode(param) resul end function dm_geocom_api_parameter_aut_atrmode pure elemental integer function dm_geocom_api_parameter_aut_posmode(param) result(n) - !! Returns `param` or `GEOCOM_AUT_NORMAL` if argument is invalid. + !! Parameterisation function for enumeration `AUT_POSMODE`. Returns + !! `param` or `GEOCOM_AUT_NORMAL` if argument is invalid. integer, intent(in) :: param !! `AUT_POSMODE`. select case (param) @@ -593,7 +596,8 @@ pure elemental integer function dm_geocom_api_parameter_aut_posmode(param) resul end function dm_geocom_api_parameter_aut_posmode pure elemental integer function dm_geocom_api_parameter_bap_prismtype(param) result(n) - !! Returns `param` or `GEOCOM_BAP_PRISM_ROUND` if argument is invalid. + !! Parameterisation function for enumeration `BAP_PRISMTYPE`. Returns + !! `param` or `GEOCOM_BAP_PRISM_ROUND` if argument is invalid. integer, intent(in) :: param !! `BAP_PRISMTYPE`. select case (param) @@ -617,7 +621,8 @@ pure elemental integer function dm_geocom_api_parameter_bap_prismtype(param) res end function dm_geocom_api_parameter_bap_prismtype pure elemental integer function dm_geocom_api_parameter_img_mem_type(param) result(n) - !! Returns `param` or `GEOCOM_IMG_INTERNAL_MEMORY` if argument is invalid. + !! Parameterisation function for enumeration `IMG_MEM_TYPE`. Returns + !! `param` or `GEOCOM_IMG_INTERNAL_MEMORY` if argument is invalid. integer, intent(in) :: param !! `IMG_MEM_TYPE`. select case (param) @@ -630,7 +635,8 @@ pure elemental integer function dm_geocom_api_parameter_img_mem_type(param) resu end function dm_geocom_api_parameter_img_mem_type pure elemental integer function dm_geocom_api_parameter_tmc_incline_prg(param) result(n) - !! Returns `param` or `GEOCOM_TMC_MEA_INC` if argument is invalid. + !! Parameterisation function for enumeration `TMC_INCLINE_PRG`. Returns + !! `param` or `GEOCOM_TMC_MEA_INC` if argument is invalid. integer, intent(in) :: param !! `TMC_INCLINE_PRG`. select case (param) @@ -644,7 +650,8 @@ pure elemental integer function dm_geocom_api_parameter_tmc_incline_prg(param) r end function dm_geocom_api_parameter_tmc_incline_prg pure elemental integer function dm_geocom_api_parameter_tmc_measure_prg(param) result(n) - !! Returns `param` or `GEOCOM_TMC_DEF_DIST` if argument is invalid. + !! Parameterisation function for enumeration `TMC_MEASURE_PRG`. Returns + !! `param` or `GEOCOM_TMC_DEF_DIST` if argument is invalid. integer, intent(in) :: param !! `TMC_MEASURE_PRG`. select case (param) @@ -673,7 +680,7 @@ pure subroutine dm_geocom_api_request(request, code, arguments, pattern, respons character(len=*), intent(in), optional :: arguments !! GeoCOM request arguments. character(len=*), intent(in), optional :: pattern !! Regular expression pattern that matches the raw response. type(response_type), intent(in), optional :: responses(:) !! Array of response types. - integer, intent(in), optional :: mode !! Mode of returned request (`REQUEST_MODE_*`). + integer, intent(in), optional :: mode !! Mode of returned observation request (`REQUEST_MODE_*`). integer :: n @@ -909,7 +916,7 @@ pure subroutine dm_geocom_api_request_delete(request, device_type, file_type, da call dm_geocom_api_request(request, REQCODE, args, PATTERN, responses) end subroutine dm_geocom_api_request_delete - pure subroutine dm_geocom_api_request_do_measure(request, prog, mode) + pure subroutine dm_geocom_api_request_do_measure(request, prog, inc_mode) !! Request of `TMC_DoMeasure` procedure. Creates request for trying a !! distance measurement. This command does not return any values. !! @@ -925,8 +932,8 @@ pure subroutine dm_geocom_api_request_do_measure(request, prog, mode) !! * `TMC_RED_TRK_DIST` !! * `TMC_FREQUENCY` !! - !! The argument `mode` (`TMC_INCLINE_PRG`) may be one of the following - !! inclination measurement modes: + !! The argument `inc_mode` (`TMC_INCLINE_PRG`) may be one of the + !! following inclination measurement modes: !! !! * `TMC_MEA_INC` !! * `TMC_AUTO_INC` @@ -942,18 +949,18 @@ pure subroutine dm_geocom_api_request_do_measure(request, prog, mode) !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2008:,` | + !! | ASCII request | `%R1Q,2008:,` | !! | ASCII response | `%R1P,0,0:` | !! integer, parameter :: REQCODE = 2008 - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: prog !! TMC measurement program (`TMC_MEASURE_PRG`). - integer, intent(in) :: mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: prog !! TMC measurement program (`TMC_MEASURE_PRG`). + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). character(len=80) :: args - write (args, '(i0, ",", i0)') prog, mode + write (args, '(i0, ",", i0)') prog, inc_mode call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_do_measure @@ -1045,7 +1052,7 @@ pure subroutine dm_geocom_api_request_fine_adjust(request, search_hz, search_v) call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_fine_adjust - pure subroutine dm_geocom_api_request_get_angle(request, mode) + pure subroutine dm_geocom_api_request_get_angle(request, inc_mode) !! Request of `TMC_GetAngle5` procedure. Creates request for returning !! a simple angle measurement. !! @@ -1060,19 +1067,19 @@ pure subroutine dm_geocom_api_request_get_angle(request, mode) !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2107:` | + !! | ASCII request | `%R1Q,2107:` | !! | ASCII response | `%R1P,0,0:,,` | !! integer, parameter :: REQCODE = 2107 character(len=*), parameter :: PATTERN = '(?\d+),(?[\d\.]+),(?[\d\.]+)' - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination sensor measurement mode (`TMC_INCLINE_PRG`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). character(len=80) :: args type(response_type) :: responses(3) - write (args, '(i0)') mode + write (args, '(i0)') inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & ! GeoCOM return code. @@ -1083,7 +1090,7 @@ pure subroutine dm_geocom_api_request_get_angle(request, mode) call dm_geocom_api_request(request, REQCODE, args, PATTERN, responses) end subroutine dm_geocom_api_request_get_angle - pure subroutine dm_geocom_api_request_get_angle_complete(request, mode) + pure subroutine dm_geocom_api_request_get_angle_complete(request, inc_mode) !! Request of `TMC_GetAngle1` procedure. Creates request for returning !! a complete angle measurement. !! @@ -1106,7 +1113,7 @@ pure subroutine dm_geocom_api_request_get_angle_complete(request, mode) !! | Property | Values | !! |----------------|--------------------------------------------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2003:` | + !! | ASCII request | `%R1Q,2003:` | !! | ASCII response | `%R1P,0,0:,,,,,,,,,` | !! integer, parameter :: REQCODE = 2003 @@ -1114,13 +1121,13 @@ pure subroutine dm_geocom_api_request_get_angle_complete(request, mode) '(?\d+),(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+),(?\d+),' // & '(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+),(?\d+),(?\d+)' - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination sensor measurement mode (`TMC_INCLINE_PRG`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). character(len=80) :: args type(response_type) :: responses(10) - write (args, '(i0)') mode + write (args, '(i0)') inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & ! GeoCOM return code. @@ -1359,7 +1366,7 @@ pure subroutine dm_geocom_api_request_get_config(request) call dm_geocom_api_request(request, REQCODE, pattern=PATTERN, responses=responses) end subroutine dm_geocom_api_request_get_config - pure subroutine dm_geocom_api_request_get_coordinate(request, mode, wait_time) + pure subroutine dm_geocom_api_request_get_coordinate(request, inc_mode, wait_time) !! Request of `TMC_GetCoordinate` procedure. Creates request for !! getting the coordinates of a measured point. !! @@ -1387,7 +1394,7 @@ pure subroutine dm_geocom_api_request_get_coordinate(request, mode, wait_time) !! | Property | Values | !! |----------------|--------------------------------------------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2082:,` | + !! | ASCII request | `%R1Q,2082:,` | !! | ASCII response | `%R1P,0,0:,,,,,,,,` | !! integer, parameter :: REQCODE = 2082 @@ -1396,13 +1403,13 @@ pure subroutine dm_geocom_api_request_get_coordinate(request, mode, wait_time) '(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+),(?\d+)' type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). - integer, intent(in) :: wait_time !! Delay to wait [ms]. + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). + integer, intent(in) :: wait_time !! Delay to wait for the distance measurement to finish [ms]. character(len=80) :: args type(response_type) :: responses(9) - write (args, '(i0, ",", i0)') wait_time, mode + write (args, '(i0, ",", i0)') wait_time, inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & ! GeoCOM return code. @@ -1684,7 +1691,7 @@ pure subroutine dm_geocom_api_request_get_fine_adjust_mode(request) call dm_geocom_api_request(request, REQCODE, pattern=PATTERN, responses=responses) end subroutine dm_geocom_api_request_get_fine_adjust_mode - pure subroutine dm_geocom_api_request_get_full_measurement(request, mode, wait_time) + pure subroutine dm_geocom_api_request_get_full_measurement(request, inc_mode, wait_time) !! Request of `TMC_GetFullMeas` procedure. Creates request to query !! angle, inclination, and distance measurement values. !! @@ -1709,10 +1716,10 @@ pure subroutine dm_geocom_api_request_get_full_measurement(request, mode, wait_t !! * `sdist` – Slope distance [m]. !! * `disttime` – Time of distance measurement [ms]. !! - !! | Property | Values | - !! |----------------|----------------------------------------------------------------------------------| - !! | Instruments | TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2167:,` | + !! | Property | Values | + !! |----------------|------------------------------------------------------------------------------| + !! | Instruments | TPS1200, TM30/TS30, TS16 | + !! | ASCII request | `%R1Q,2167:,` | !! | ASCII response | `%R1P,0,0:,,,,,,,,` | !! integer, parameter :: REQCODE = 2167 @@ -1721,13 +1728,13 @@ pure subroutine dm_geocom_api_request_get_full_measurement(request, mode, wait_t '(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+)' type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). integer, intent(in) :: wait_time !! Delay to wait for the distance measurement to finish [ms]. character(len=80) :: args type(response_type) :: responses(9) - write (args, '(i0, ",", i0)') wait_time, mode + write (args, '(i0, ",", i0)') wait_time, inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & ! GeoCOM return code. @@ -2466,7 +2473,7 @@ pure subroutine dm_geocom_api_request_get_signal(request) call dm_geocom_api_request(request, REQCODE, pattern=PATTERN, responses=responses) end subroutine dm_geocom_api_request_get_signal - pure subroutine dm_geocom_api_request_get_simple_coordinates(request, mode, wait_time) + pure subroutine dm_geocom_api_request_get_simple_coordinates(request, inc_mode, wait_time) !! Request of `TMC_GetSimpleCoord` procedure. Creates request for !! returning cartesian coordinates. !! @@ -2487,7 +2494,7 @@ pure subroutine dm_geocom_api_request_get_simple_coordinates(request, mode, wait !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2116:,` | + !! | ASCII request | `%R1Q,2116:,` | !! | ASCII response | `%R1P,0,0:,,,` | !! integer, parameter :: REQCODE = 2116 @@ -2495,13 +2502,13 @@ pure subroutine dm_geocom_api_request_get_simple_coordinates(request, mode, wait '(?\d+),(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+)' type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). integer, intent(in) :: wait_time !! Delay to wait for the distance measurement to finish [ms]. character(len=80) :: args type(response_type) :: responses(4) - write (args, '(i0, ",", i0)') wait_time, mode + write (args, '(i0, ",", i0)') wait_time, inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & @@ -2513,7 +2520,7 @@ pure subroutine dm_geocom_api_request_get_simple_coordinates(request, mode, wait call dm_geocom_api_request(request, REQCODE, pattern=PATTERN, responses=responses) end subroutine dm_geocom_api_request_get_simple_coordinates - pure subroutine dm_geocom_api_request_get_simple_measurement(request, mode, wait_time) + pure subroutine dm_geocom_api_request_get_simple_measurement(request, inc_mode, wait_time) !! Request of `TMC_GetSimpleMea` procedure. Creates request for !! returning the values of the angle and distance measurement. !! @@ -2531,20 +2538,20 @@ pure subroutine dm_geocom_api_request_get_simple_measurement(request, mode, wait !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2108:,` | + !! | ASCII request | `%R1Q,2108:,` | !! | ASCII response | `%R1P,0,0:,,,` | !! integer, parameter :: REQCODE = 2108 character(len=*), parameter :: PATTERN = '(?\d+),(?[-\d\.]+),(?[-\d\.]+),(?[-\d\.]+)' type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). integer, intent(in) :: wait_time !! Delay to wait for the distance measurement to finish [ms]. character(len=80) :: args type(response_type) :: responses(4) - write (args, '(i0, ",", i0)') wait_time, mode + write (args, '(i0, ",", i0)') wait_time, inc_mode responses = [ & response_type('grc', unit=' ', type=RESPONSE_TYPE_INT32), & @@ -3364,7 +3371,7 @@ pure subroutine dm_geocom_api_request_set_date_time(request, year, month, day, h call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_date_time - pure subroutine dm_geocom_api_request_set_distance(request, slope_dist, height_offset, mode) + pure subroutine dm_geocom_api_request_set_distance(request, slope_dist, height_offset, inc_mode) !! Request of `TMC_SetHandDist` procedure. Creates request for !! setting the slope distance and height offset. !! @@ -3375,7 +3382,7 @@ pure subroutine dm_geocom_api_request_set_distance(request, slope_dist, height_o !! 3π/2, depending on the face of the instrument. The previously !! measured distance is cleared. !! - !! The argument `mode` (`TMC_INCLINE_PRG`) must be one of the + !! The argument `inc_mode` (`TMC_INCLINE_PRG`) must be one of the !! following: !! !! * `TMC_MEA_INC` – Use sensor (a priori sigma). @@ -3386,22 +3393,22 @@ pure subroutine dm_geocom_api_request_set_distance(request, slope_dist, height_o !! !! * `grc` – GeoCOM return code. !! - !! | Property | Values | - !! |----------------|--------------------------------------------------| - !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,2019:,,` | - !! | ASCII response | `%R1P,0,0:` | + !! | Property | Values | + !! |----------------|------------------------------------------------------| + !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | + !! | ASCII request | `%R1Q,2019:,,` | + !! | ASCII response | `%R1P,0,0:` | !! integer, parameter :: REQCODE = 2019 type(request_type), intent(out) :: request !! Prepared request. real(kind=r8), intent(in) :: slope_dist !! Slope distance [m]. real(kind=r8), intent(in) :: height_offset !! Height offset [m]. - integer, intent(in) :: mode !! Inclination mode (`TMC_INCLINE_PRG`). + integer, intent(in) :: inc_mode !! Inclination measurement mode (`TMC_INCLINE_PRG`). character(len=80) :: args - write (args, '(2(f0.12, ","), i0)') slope_dist, height_offset, mode + write (args, '(2(f0.12, ","), i0)') slope_dist, height_offset, inc_mode call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_distance @@ -3498,7 +3505,7 @@ pure subroutine dm_geocom_api_request_set_egl_intensity(request, intensity) call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_egl_intensity - pure subroutine dm_geocom_api_request_set_fine_adjust_mode(request, mode) + pure subroutine dm_geocom_api_request_set_fine_adjust_mode(request, adj_mode) !! Request of `AUT_SetFineAdjustMode` procedure. Creates request for !! setting the fine adjust positioning mode. !! @@ -3507,7 +3514,7 @@ pure subroutine dm_geocom_api_request_set_fine_adjust_mode(request, mode) !! robotic licence). If a target is near or held by hand, it is !! recommended to set the adjust mode to `AUT_POINT_MODE`. !! - !! The argument `mode` has to be either `AUT_NORM_MODE` or + !! The argument `adj_mode` has to be either `AUT_NORM_MODE` or !! `AUT_POINT_MODE`. !! !! The instrument returns the following responses: @@ -3517,17 +3524,17 @@ pure subroutine dm_geocom_api_request_set_fine_adjust_mode(request, mode) !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,9031:` | + !! | ASCII request | `%R1Q,9031:` | !! | ASCII response | `%R1P,0,0:` | !! integer, parameter :: REQCODE = 9031 - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Fine adjust positioning mode (`AUT_ADJMODE`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: adj_mode !! Fine adjust positioning mode (`AUT_ADJMODE`). character(len=80) :: args - write (args, '(i0)') mode + write (args, '(i0)') adj_mode call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_fine_adjust_mode @@ -3889,11 +3896,11 @@ pure subroutine dm_geocom_api_request_set_prism_type_v2(request, prism_type, pri call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_prism_type_v2 - pure subroutine dm_geocom_api_request_set_reduced_atr_fov(request, reduced) + pure subroutine dm_geocom_api_request_set_reduced_atr_fov(request, enabled) !! Request of `BAP_SetRedATRFov` procedure. Creates request for !! setting the reduced ATR field of view. !! - !! If `reduced` is `.true.`, ATR uses reduced field of view (about + !! If `enabled` is `.true.`, ATR uses reduced field of view (about !! 1/9), full field of view otherwise. !! !! The instrument returns the following responses: @@ -3909,11 +3916,11 @@ pure subroutine dm_geocom_api_request_set_reduced_atr_fov(request, reduced) integer, parameter :: REQCODE = 17008 type(request_type), intent(out) :: request !! Prepared request. - logical, intent(in) :: reduced !! Use reduced field of view. + logical, intent(in) :: enabled !! Use reduced field of view. character(len=80) :: args - write (args, '(i1)') dm_btoi(reduced) + write (args, '(i1)') dm_btoi(enabled) call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_set_reduced_atr_fov @@ -4378,11 +4385,11 @@ pure subroutine dm_geocom_api_request_stop_controller(request, stop_mode) call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_stop_controller - pure subroutine dm_geocom_api_request_switch_off(request, mode) + pure subroutine dm_geocom_api_request_switch_off(request, stop_mode) !! Request of `COM_SwitchOffTPS` procedure. Creates request for !! turning the instrument off. !! - !! The argument `mode` has to be one of the following: + !! The argument `stop_mode` has to be one of the following: !! !! * `COM_TPS_STOP_SHUT_DOWN` – Power down instrument. !! * `COM_TPS_STOP_SLEEP` – Sleep mode (not supported by TPS1200). @@ -4399,42 +4406,44 @@ pure subroutine dm_geocom_api_request_switch_off(request, mode) !! integer, parameter :: REQCODE = 112 - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Switch off mode (`COM_TPS_STOP_MODE`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: stop_mode !! Switch off mode (`COM_TPS_STOP_MODE`). character(len=80) :: args - write (args, '(i0)') mode + write (args, '(i0)') stop_mode call dm_geocom_api_request(request, REQCODE, args, GEOCOM_GRC_PATTERN, GEOCOM_GRC_RESPONSES) end subroutine dm_geocom_api_request_switch_off - pure subroutine dm_geocom_api_request_switch_on(request, mode) + pure subroutine dm_geocom_api_request_switch_on(request, start_mode) !! Request of `COM_SwitchOnTPS` procedure. Creates request for turning !! the instrument on. !! - !! The argument `mode` has to be one of the following: + !! The argument `start_mode` has to be one of the following: !! !! * `COM_TPS_STARTUP_LOCAL` – Not supported by TPS1200. !! * `COM_TPS_STARTUP_REMOTE` – Online mode (RPC is enabled). !! - !! The instrument returns the following responses: + !! The instrument may return the following responses: !! !! * `grc` – GeoCOM return code. !! + !! The response is not captured by the returned request. + !! !! | Property | Values | !! |----------------|--------------------------------------------------| !! | Instruments | TPS1100, TPS1200, TM30/TS30, TS16 | - !! | ASCII request | `%R1Q,111:` | + !! | ASCII request | `%R1Q,111:` | !! | ASCII response | `%R1P,0,0:5` (if switched on) | !! integer, parameter :: REQCODE = 111 - type(request_type), intent(out) :: request !! Prepared request. - integer, intent(in) :: mode !! Switch on mode (`COM_TPS_STARTUP_MODE`). + type(request_type), intent(out) :: request !! Prepared request. + integer, intent(in) :: start_mode !! Switch on mode (`COM_TPS_STARTUP_MODE`). character(len=80) :: args - write (args, '(i0)') mode + write (args, '(i0)') start_mode call dm_geocom_api_request(request, REQCODE, args) end subroutine dm_geocom_api_request_switch_on diff --git a/src/dm_hdf5.f90 b/src/dm_hdf5.f90 index 1bffcc9..f45c6d8 100644 --- a/src/dm_hdf5.f90 +++ b/src/dm_hdf5.f90 @@ -493,6 +493,13 @@ integer function hdf5_create_observ(type_id) result(rc) call h5tinsert_f(type_id, 'name', offset, tid, stat); if (stat < 0) return call h5tclose_f(tid, stat); if (stat < 0) return + ! Observation source. + dims(1) = int(OBSERV_SOURCE_LEN, kind=hsize_t) + offset = h5offsetof(c_loc(observ), c_loc(observ%source)) + call h5tarray_create_f(H5T_NATIVE_CHARACTER, 1, dims, tid, stat); if (stat < 0) return + call h5tinsert_f(type_id, 'source', offset, tid, stat); if (stat < 0) return + call h5tclose_f(tid, stat); if (stat < 0) return + ! Observation timestamp. dims(1) = int(TIME_LEN, kind=hsize_t) offset = h5offsetof(c_loc(observ), c_loc(observ%timestamp)) diff --git a/src/dm_html.f90 b/src/dm_html.f90 index 575ebbf..f2eda85 100644 --- a/src/dm_html.f90 +++ b/src/dm_html.f90 @@ -1133,6 +1133,8 @@ function dm_html_observ(observ, prefix_node, prefix_sensor, prefix_target) resul H_TD // tid // H_TD_END // H_TR_END // & H_TR // H_TH // 'Name' // H_TH_END // & H_TD // dm_html_encode(observ%name) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Source' // H_TH_END // & + H_TD // dm_html_encode(observ%source) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Timestamp' // H_TH_END // & H_TD // dm_html_encode(observ%timestamp) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Path' // H_TH_END // & diff --git a/src/dm_json.f90 b/src/dm_json.f90 index 506e3a2..8b6970e 100644 --- a/src/dm_json.f90 +++ b/src/dm_json.f90 @@ -330,6 +330,7 @@ function json_from_observ(observ) result(json) ' "sensor_id": "' // trim(observ%sensor_id) // '",' // & ' "target_id": "' // trim(observ%target_id) // '",' // & ' "name": "' // trim(observ%name) // '",' // & + ' "source": "' // trim(observ%source) // '",' // & ' "timestamp": "' // trim(observ%timestamp) // '",' // & ' "path": "' // json_escape(observ%path) // '",' // & ' "priority": ' // dm_itoa(observ%priority) // ',' // & diff --git a/src/dm_log.f90 b/src/dm_log.f90 index 26a370b..f0b1c57 100644 --- a/src/dm_log.f90 +++ b/src/dm_log.f90 @@ -5,10 +5,10 @@ module dm_log use :: dm_error use :: dm_id use :: dm_kind - use :: dm_node - use :: dm_observ - use :: dm_sensor - use :: dm_target + use :: dm_node, only: NODE_ID_LEN + use :: dm_observ, only: OBSERV_ID_LEN + use :: dm_sensor, only: SENSOR_ID_LEN + use :: dm_target, only: TARGET_ID_LEN use :: dm_time use :: dm_uuid implicit none (type, external) @@ -132,7 +132,14 @@ pure elemental logical function dm_log_valid_level(level) result(valid) end function dm_log_valid_level pure elemental logical function dm_log_valid_log(log) result(valid) - !! Returns `.true.` if given log is valid. + !! Returns `.true.` if given log is valid. A log is valid if it conforms + !! to the following rules: + !! + !! * The log level and the error code are valid. + !! * The log id is a valid UUID and not the default UUID. + !! * The time stamp is in ISO 8601 format. + !! * All ASCII characters of the log message are printable. + use :: dm_string, only: dm_string_is_printable type(log_type), intent(in) :: log !! Log to validate. valid = .false. @@ -142,6 +149,7 @@ pure elemental logical function dm_log_valid_log(log) result(valid) if (log%id == UUID_DEFAULT) return if (.not. dm_uuid4_valid(log%id)) return if (.not. dm_time_valid(log%timestamp)) return + if (.not. dm_string_is_printable(log%message)) return valid = .true. end function dm_log_valid_log diff --git a/src/dm_lua.f90 b/src/dm_lua.f90 index a73aa56..d2b9ed3 100644 --- a/src/dm_lua.f90 +++ b/src/dm_lua.f90 @@ -1061,6 +1061,7 @@ integer function lua_to_observ(lua, observ) result(rc) rc = dm_lua_field(lua, 'target_id', observ%target_id) rc = dm_lua_field(lua, 'id', observ%id) rc = dm_lua_field(lua, 'name', observ%name) + rc = dm_lua_field(lua, 'source', observ%source) rc = dm_lua_field(lua, 'timestamp', observ%timestamp) rc = dm_lua_field(lua, 'path', observ%path, unescape=.true.) rc = dm_lua_field(lua, 'priority', observ%priority) @@ -1325,6 +1326,9 @@ subroutine lua_from_observ(lua, observ) ptr = lua_pushstring(lua%ptr, trim(observ%name)) call lua_setfield(lua%ptr, -2, 'name') + ptr = lua_pushstring(lua%ptr, trim(observ%source)) + call lua_setfield(lua%ptr, -2, 'source') + ptr = lua_pushstring(lua%ptr, trim(observ%timestamp)) call lua_setfield(lua%ptr, -2, 'timestamp') diff --git a/src/dm_lua_geocom.f90 b/src/dm_lua_geocom.f90 index ca4c833..6a05f6b 100644 --- a/src/dm_lua_geocom.f90 +++ b/src/dm_lua_geocom.f90 @@ -641,14 +641,14 @@ end function lua_geocom_delete integer(kind=c_int) function lua_geocom_do_measure(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode, prog + integer :: inc_mode, prog type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - prog = dm_geocom_api_parameter_tmc_measure_prg(dm_lua_to_int32(lua, 1)) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 2)) - call dm_geocom_api_request_do_measure(request, prog, mode) + prog = dm_geocom_api_parameter_tmc_measure_prg(dm_lua_to_int32(lua, 1)) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 2)) + call dm_geocom_api_request_do_measure(request, prog, inc_mode) call dm_lua_from(lua, request) n = 1 end function lua_geocom_do_measure @@ -685,13 +685,13 @@ end function lua_geocom_fine_adjust integer(kind=c_int) function lua_geocom_get_angle(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode + integer :: inc_mode type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) - call dm_geocom_api_request_get_angle(request, mode) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + call dm_geocom_api_request_get_angle(request, inc_mode) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_angle @@ -699,13 +699,13 @@ end function lua_geocom_get_angle integer(kind=c_int) function lua_geocom_get_angle_complete(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode + integer :: inc_mode type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) - call dm_geocom_api_request_get_angle_complete(request, mode) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + call dm_geocom_api_request_get_angle_complete(request, inc_mode) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_angle_complete @@ -797,14 +797,14 @@ end function lua_geocom_get_config integer(kind=c_int) function lua_geocom_get_coordinate(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode, wait_time + integer :: inc_mode, wait_time type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) wait_time = max(0, dm_lua_to_int32(lua, 2)) - call dm_geocom_api_request_get_coordinate(request, mode, wait_time) + call dm_geocom_api_request_get_coordinate(request, inc_mode, wait_time) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_coordinate @@ -908,14 +908,14 @@ end function lua_geocom_get_fine_adjust_mode integer(kind=c_int) function lua_geocom_get_full_measurement(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode, wait_time + integer :: inc_mode, wait_time type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) wait_time = max(0, dm_lua_to_int32(lua, 2)) - call dm_geocom_api_request_get_full_measurement(request, mode, wait_time) + call dm_geocom_api_request_get_full_measurement(request, inc_mode, wait_time) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_full_measurement @@ -1191,14 +1191,14 @@ end function lua_geocom_get_signal integer(kind=c_int) function lua_geocom_get_simple_coordinates(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode, wait_time + integer :: inc_mode, wait_time type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) wait_time = max(0, dm_lua_to_int32(lua, 2)) - call dm_geocom_api_request_get_simple_coordinates(request, mode, wait_time) + call dm_geocom_api_request_get_simple_coordinates(request, inc_mode, wait_time) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_simple_coordinates @@ -1206,14 +1206,14 @@ end function lua_geocom_get_simple_coordinates integer(kind=c_int) function lua_geocom_get_simple_measurement(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. - integer :: mode, wait_time + integer :: inc_mode, wait_time type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) + inc_mode = dm_geocom_api_parameter_tmc_incline_prg(dm_lua_to_int32(lua, 1)) wait_time = max(0, dm_lua_to_int32(lua, 2)) - call dm_geocom_api_request_get_simple_measurement(request, mode, wait_time) + call dm_geocom_api_request_get_simple_measurement(request, inc_mode, wait_time) call dm_lua_from(lua, request) n = 1 end function lua_geocom_get_simple_measurement @@ -1768,11 +1768,13 @@ end function lua_geocom_set_prism_type_v2 integer(kind=c_int) function lua_geocom_set_reduced_atr_fov(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. + logical :: enabled type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - ! call dm_geocom_api_request_set_reduced_atr_fov(request, reduced) + enabled = dm_lua_to_logical(lua, 1) + call dm_geocom_api_request_set_reduced_atr_fov(request, enabled) call dm_lua_from(lua, request) n = 1 end function lua_geocom_set_reduced_atr_fov @@ -1898,11 +1900,14 @@ end function lua_geocom_set_user_spiral integer(kind=c_int) function lua_geocom_set_velocity(ptr) bind(c) result(n) type(c_ptr), intent(in), value :: ptr !! Lua state pointer. + real(kind=r8) :: omega_hz, omega_v type(lua_state_type) :: lua type(request_type) :: request lua = lua_state_type(ptr) - ! call dm_geocom_api_request_set_velocity(request, omega_hz, omega_v) + omega_hz = dm_lua_to_real64(lua, 1) + omega_v = dm_lua_to_real64(lua, 2) + call dm_geocom_api_request_set_velocity(request, omega_hz, omega_v) call dm_lua_from(lua, request) n = 1 end function lua_geocom_set_velocity @@ -1962,7 +1967,7 @@ integer(kind=c_int) function lua_geocom_switch_off(ptr) bind(c) result(n) type(request_type) :: request lua = lua_state_type(ptr) - ! call dm_geocom_api_request_switch_off(request, mode) + ! call dm_geocom_api_request_switch_off(request, stop_mode) call dm_lua_from(lua, request) n = 1 end function lua_geocom_switch_off @@ -1974,7 +1979,7 @@ integer(kind=c_int) function lua_geocom_switch_on(ptr) bind(c) result(n) type(request_type) :: request lua = lua_state_type(ptr) - ! call dm_geocom_api_request_switch_on(request, mode) + ! call dm_geocom_api_request_switch_on(request, start_mode) call dm_lua_from(lua, request) n = 1 end function lua_geocom_switch_on diff --git a/src/dm_mqueue_util.f90 b/src/dm_mqueue_util.f90 index 02467ce..243be52 100644 --- a/src/dm_mqueue_util.f90 +++ b/src/dm_mqueue_util.f90 @@ -128,8 +128,8 @@ integer function mqueue_forward_observ(observ, name, blocking, quiet, self) resu end if if (.not. quiet_) then - call dm_log(LOG_DEBUG, 'sent observ ' // trim(observ%name) // ' to mqueue /' // & - observ%receivers(next), observ=observ) + call dm_log(LOG_DEBUG, 'sent observ ' // trim(observ%name) // ' from ' // & + trim(observ%source) // ' to mqueue /' // observ%receivers(next), observ=observ) end if end block mqueue_block diff --git a/src/dm_observ.f90 b/src/dm_observ.f90 index bfdea97..692124d 100644 --- a/src/dm_observ.f90 +++ b/src/dm_observ.f90 @@ -22,6 +22,7 @@ module dm_observ ! ****************************************************************** integer, parameter, public :: OBSERV_ID_LEN = UUID_LEN !! Observation id length. integer, parameter, public :: OBSERV_NAME_LEN = ID_LEN !! Observation name length. + integer, parameter, public :: OBSERV_SOURCE_LEN = ID_LEN !! Observation source length. integer, parameter, public :: OBSERV_PATH_LEN = 32 !! Observation path length. integer, parameter, public :: OBSERV_RECEIVER_LEN = ID_LEN !! Observation receiver length. integer, parameter, public :: OBSERV_MAX_NRECEIVERS = 16 !! Max. number of receivers. @@ -36,6 +37,7 @@ module dm_observ character(len=SENSOR_ID_LEN) :: sensor_id = ' ' !! Sensor id. character(len=TARGET_ID_LEN) :: target_id = ' ' !! Target id. character(len=OBSERV_NAME_LEN) :: name = ' ' !! Observation name. + character(len=OBSERV_SOURCE_LEN) :: source = ' ' !! Observation source. character(len=TIME_LEN) :: timestamp = ' ' !! ISO 8601 timestamp. character(len=OBSERV_PATH_LEN) :: path = ' ' !! TTY/PTY path. integer :: priority = 0 !! Message queue priority (>= 0). @@ -98,7 +100,7 @@ module dm_observ ! PUBLIC PROCEDURES. ! ****************************************************************** integer function dm_observ_add_receiver(observ, receiver) result(rc) - !! Adds receiver to observation. + !! Validates and adds receiver to observation. !! !! Returns the following error codes: !! @@ -107,7 +109,6 @@ integer function dm_observ_add_receiver(observ, receiver) result(rc) !! longer than the maximum `OBSERV_RECEIVER_LEN`. type(observ_type), intent(inout) :: observ !! Observation type. character(len=*), intent(in) :: receiver !! Receiver name. - integer :: n rc = E_BOUNDS if (observ%nreceivers < 0 .or. observ%nreceivers >= OBSERV_MAX_NRECEIVERS) return @@ -123,7 +124,8 @@ end function dm_observ_add_receiver integer function dm_observ_add_request(observ, request) result(rc) !! Appends a request to an observation. Returns `E_BOUNDS` if the list - !! of requests is full. + !! of requests is full. The function does not validate the given + !! request. type(observ_type), intent(inout) :: observ !! Observation type. type(request_type), intent(inout) :: request !! Request type. @@ -150,6 +152,7 @@ pure elemental logical function dm_observ_equals(observ1, observ2) result(equals if (observ1%sensor_id /= observ2%sensor_id) return if (observ1%target_id /= observ2%target_id) return if (observ1%name /= observ2%name) return + if (observ1%source /= observ2%source) return if (observ1%timestamp /= observ2%timestamp) return if (observ1%path /= observ2%path) return if (observ1%priority /= observ2%priority) return @@ -210,23 +213,24 @@ pure elemental logical function dm_observ_valid(observ, id, timestamp) result(va !! Returns `.true.` if given observation is valid. An observation is !! valid if it conforms to the following rules: !! - !! * Valid observation, node, sensor and target ids are set, and the - !! observation id does not equal the default UUID, unless argument - !! `id` is passed and `.false.`. + !! * A valid observation id, node id, sensor id, and target id are set, + !! and the observation id does not equal the default UUID, unless + !! argument `id` is passed and `.false.`. !! * The observation name is a valid id (limited character set, no !! white spaces). - !! * The time stamp is in ISO 8601 format, unless argument `timestamp` - !! is passed and `.false.`. - !! * The attributes _priority_ and _error_ are not negative. + !! * The attribute _timestamp_ is set and in ISO 8601 format, unless + !! argument `timestamp` is passed and `.false.`. + !! * The attributes _priority_ is not negative. + !! * The attribute _error_ is a valid error code. !! * The attributes _next_ and _nreceivers_ are within the bounds of !! the array _receivers_, or 0. !! * The attribute _nrequests_ is within the bounds of the array - !! _receivers_, or 0. + !! _requests_, or 0. !! * All receiver names are valid ids. !! * All requests and responses are valid. type(observ_type), intent(in) :: observ !! Observation type. - logical, intent(in), optional :: id !! Validate ids. - logical, intent(in), optional :: timestamp !! Validate timestamps. + logical, intent(in), optional :: id !! Validate or ignore ids. + logical, intent(in), optional :: timestamp !! Validate or ignore timestamps. integer :: i logical :: id_, timestamp_ @@ -248,6 +252,9 @@ pure elemental logical function dm_observ_valid(observ, id, timestamp) result(va end if if (.not. dm_id_valid(observ%name)) return + if (len_trim(observ%source) > 0) then + if (.not. dm_id_valid(observ%source)) return + end if if (timestamp_) then if (.not. dm_time_valid(observ%timestamp)) return @@ -311,6 +318,7 @@ subroutine dm_observ_out(observ, unit) write (unit_, '("observ.sensor_id: ", a)') trim(observ%sensor_id) write (unit_, '("observ.target_id: ", a)') trim(observ%target_id) write (unit_, '("observ.name: ", a)') trim(observ%name) + write (unit_, '("observ.source: ", a)') trim(observ%source) write (unit_, '("observ.timestamp: ", a)') observ%timestamp write (unit_, '("observ.path: ", a)') trim(observ%path) write (unit_, '("observ.priority: ", i0)') observ%priority diff --git a/src/dm_request.f90 b/src/dm_request.f90 index d720ee4..081befb 100644 --- a/src/dm_request.f90 +++ b/src/dm_request.f90 @@ -202,15 +202,15 @@ pure elemental logical function dm_request_valid(request, timestamp) result(vali !! !! * A time stamp is set and in ISO 8601 format, unless argument !! `timestamp` is passed and `.false.`. - !! * All characters in attribute _request_ are printable. + !! * All ASCII characters in attribute _request_ are printable. !! * The attributes _delay_, _retries_, _state_ and _timeout_ are not !! negative. !! * The attribute _error_ is a valid error code. !! * The attribute _nresponses_ is within the bounds of array - !! _nresponses_. - !! * All reponses are valid. + !! _responses_. + !! * All responses are valid. type(request_type), intent(in) :: request !! Request type. - logical, intent(in), optional :: timestamp !! Validate timestamp. + logical, intent(in), optional :: timestamp !! Validate or ignore timestamp. logical :: timestamp_ diff --git a/src/dm_sql.f90 b/src/dm_sql.f90 index 614ee42..8061a28 100644 --- a/src/dm_sql.f90 +++ b/src/dm_sql.f90 @@ -125,6 +125,7 @@ module dm_sql 'target_id INTEGER NOT NULL,' // NL // & 'id TEXT NOT NULL UNIQUE,' // NL // & 'name TEXT NOT NULL,' // NL // & + 'source TEXT,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'path TEXT,' // NL // & 'priority INTEGER NOT NULL DEFAULT 0,' // NL // & @@ -191,7 +192,7 @@ module dm_sql 'log_id INTEGER NOT NULL UNIQUE,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'code INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nattempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (log_id) REFERENCES logs(log_id)) STRICT' ! Synchronised nodes schema. @@ -201,7 +202,7 @@ module dm_sql 'node_id INTEGER NOT NULL UNIQUE,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'code INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nattempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (node_id) REFERENCES nodes(node_id)) STRICT' ! Synchronised observations schema. @@ -211,7 +212,7 @@ module dm_sql 'observ_id INTEGER NOT NULL UNIQUE,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'code INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nattempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (observ_id) REFERENCES observs(observ_id)) STRICT' ! Synchronised sensors schema. @@ -221,7 +222,7 @@ module dm_sql 'sensor_id INTEGER NOT NULL UNIQUE,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'code INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nattempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (sensor_id) REFERENCES sensors(sensor_id)) STRICT' ! Synchronised targets schema. @@ -231,7 +232,7 @@ module dm_sql 'target_id INTEGER NOT NULL UNIQUE,' // NL // & 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & 'code INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nattempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (target_id) REFERENCES targets(target_id)) STRICT' ! ****************************************************************** @@ -394,20 +395,19 @@ module dm_sql 'INSERT OR FAIL INTO targets(id, name, meta, state, x, y, z) VALUES (?, ?, ?, ?, ?, ?, ?)' ! Query to insert observation. - ! Arguments: nodes.id, sensors.id, targets.id, observs.id, - ! observs.name, observs.timestamp, observs.path, - ! observs.priority, observs.error, observs.next, - ! observs.nreceivers, observs.nrequests + ! Arguments: nodes.id, sensors.id, targets.id, observs.id, observs.name, + ! observs.source, observs.timestamp, observs.path, observs.priority, + ! observs.error, observs.next, observs.nreceivers, observs.nrequests character(len=*), parameter, public :: SQL_INSERT_OBSERV = & 'INSERT OR FAIL INTO observs ' // & - '(id, node_id, sensor_id, target_id, name, timestamp, path, ' // & + '(id, node_id, sensor_id, target_id, name, source, timestamp, path, ' // & 'priority, error, next, nreceivers, nrequests) ' // & 'VALUES (' // & '?, ' // & '(SELECT node_id FROM nodes WHERE id = ?), ' // & '(SELECT sensor_id FROM sensors WHERE id = ?), ' // & '(SELECT target_id FROM targets WHERE id = ?), ' // & - '?, ?, ?, ?, ?, ?, ?, ?)' + '?, ?, ?, ?, ?, ?, ?, ?, ?)' ! Query to insert receiver. ! Arguments: observs.id, receivers.idx, receivers.name @@ -668,6 +668,7 @@ module dm_sql 'sensors.id, ' // & 'targets.id, ' // & 'observs.name, ' // & + 'observs.source, ' // & 'observs.timestamp, ' // & 'observs.path, ' // & 'observs.priority, ' // & @@ -698,6 +699,7 @@ module dm_sql 'sensors.id, ' // & 'targets.id, ' // & 'observs.name, ' // & + 'observs.source, ' // & 'observs.timestamp, ' // & 'observs.path, ' // & 'observs.priority, ' // & @@ -921,59 +923,59 @@ module dm_sql ! SYNC QUERIES. ! ****************************************************************** ! Query to upsert sync_logs data. - ! Arguments: logs.id, sync_observs.timestamp, sync_observs.code, sync_observs.nattempts + ! Arguments: logs.id, sync_observs.timestamp, sync_observs.code, sync_observs.attempts character(len=*), parameter, public :: SQL_INSERT_SYNC_LOG = & - 'INSERT INTO sync_logs(log_id, timestamp, code, nattempts) ' // & + 'INSERT INTO sync_logs(log_id, timestamp, code, attempts) ' // & 'VALUES ((SELECT log_id FROM logs WHERE id = ?), ?, ?, ?) ' // & 'ON CONFLICT DO UPDATE SET ' // & 'log_id = excluded.log_id, ' // & 'timestamp = excluded.timestamp, ' // & 'code = excluded.code, ' // & - 'nattempts = excluded.nattempts' + 'attempts = excluded.attempts' ! Query to upsert sync_nodes data. - ! Arguments: nodes.id, sync_nodes.timestamp, sync_nodes.code, sync_nodes.nattempts + ! Arguments: nodes.id, sync_nodes.timestamp, sync_nodes.code, sync_nodes.attempts character(len=*), parameter, public :: SQL_INSERT_SYNC_NODE = & - 'INSERT INTO sync_nodes(node_id, timestamp, code, nattempts) ' // & + 'INSERT INTO sync_nodes(node_id, timestamp, code, attempts) ' // & 'VALUES ((SELECT node_id FROM nodes WHERE id = ?), ?, ?, ?) ' // & 'ON CONFLICT DO UPDATE SET ' // & 'node_id = excluded.node_id, ' // & 'timestamp = excluded.timestamp, ' // & 'code = excluded.code, ' // & - 'nattempts = excluded.nattempts' + 'attempts = excluded.attempts' ! Query to upsert sync_observs data. - ! Arguments: observs.id, sync_observs.timestamp, sync_observs.code, sync_observs.nattempts + ! Arguments: observs.id, sync_observs.timestamp, sync_observs.code, sync_observs.attempts character(len=*), parameter, public :: SQL_INSERT_SYNC_OBSERV = & - 'INSERT INTO sync_observs(observ_id, timestamp, code, nattempts) ' // & + 'INSERT INTO sync_observs(observ_id, timestamp, code, attempts) ' // & 'VALUES ((SELECT observ_id FROM observs WHERE id = ?), ?, ?, ?) ' // & 'ON CONFLICT DO UPDATE SET ' // & 'observ_id = excluded.observ_id, ' // & 'timestamp = excluded.timestamp, ' // & 'code = excluded.code, ' // & - 'nattempts = excluded.nattempts' + 'attempts = excluded.attempts' ! Query to upsert sync_sensors data. - ! Arguments: sensors.id, sync_sensors.timestamp, sync_sensors.code, sync_sensors.nattempts + ! Arguments: sensors.id, sync_sensors.timestamp, sync_sensors.code, sync_sensors.attempts character(len=*), parameter, public :: SQL_INSERT_SYNC_SENSOR = & - 'INSERT INTO sync_sensors(sensor_id, timestamp, code, nattempts) ' // & + 'INSERT INTO sync_sensors(sensor_id, timestamp, code, attempts) ' // & 'VALUES ((SELECT sensor_id FROM sensors WHERE id = ?), ?, ?, ?) ' // & 'ON CONFLICT DO UPDATE SET ' // & 'sensor_id = excluded.sensor_id, ' // & 'timestamp = excluded.timestamp, ' // & 'code = excluded.code, ' // & - 'nattempts = excluded.nattempts' + 'attempts = excluded.attempts' ! Query to upsert sync_targets data. - ! Arguments: targets.id, sync_targets.timestamp, sync_targets.code, sync_targets.nattempts + ! Arguments: targets.id, sync_targets.timestamp, sync_targets.code, sync_targets.attempts character(len=*), parameter, public :: SQL_INSERT_SYNC_TARGET = & - 'INSERT INTO sync_targets(target_id, timestamp, code, nattempts) ' // & + 'INSERT INTO sync_targets(target_id, timestamp, code, attempts) ' // & 'VALUES ((SELECT target_id FROM targets WHERE id = ?), ?, ?, ?) ' // & 'ON CONFLICT DO UPDATE SET ' // & 'target_id = excluded.target_id, ' // & 'timestamp = excluded.timestamp, ' // & 'code = excluded.code, ' // & - 'nattempts = excluded.nattempts' + 'attempts = excluded.attempts' character(len=*), parameter, public :: SQL_SELECT_NSYNC_LOGS = & 'SELECT COUNT(*) FROM logs ' // & @@ -1006,7 +1008,7 @@ module dm_sql 'logs.id, ' // & 'sync_logs.timestamp, ' // & 'sync_logs.code, ' // & - 'sync_logs.nattempts ' // & + 'sync_logs.attempts ' // & 'FROM logs ' // & 'LEFT JOIN sync_logs ON sync_logs.log_id = logs.log_id ' // & 'WHERE sync_logs.log_id IS NULL OR sync_logs.code NOT IN (201, 409) ' // & @@ -1019,7 +1021,7 @@ module dm_sql 'nodes.id, ' // & 'sync_nodes.timestamp, ' // & 'sync_nodes.code, ' // & - 'sync_nodes.nattempts ' // & + 'sync_nodes.attempts ' // & 'FROM nodes ' // & 'LEFT JOIN sync_nodes ON sync_nodes.node_id = nodes.node_id ' // & 'WHERE sync_nodes.node_id IS NULL OR sync_nodes.code NOT IN (201, 409)' @@ -1031,7 +1033,7 @@ module dm_sql 'observs.id, ' // & 'sync_observs.timestamp, ' // & 'sync_observs.code, ' // & - 'sync_observs.nattempts ' // & + 'sync_observs.attempts ' // & 'FROM observs ' // & 'LEFT JOIN sync_observs ON sync_observs.observ_id = observs.observ_id ' // & 'WHERE sync_observs.observ_id IS NULL OR sync_observs.code NOT IN (201, 409) ' // & @@ -1044,7 +1046,7 @@ module dm_sql 'sensors.id, ' // & 'sync_sensors.timestamp, ' // & 'sync_sensors.code, ' // & - 'sync_sensors.nattempts ' // & + 'sync_sensors.attempts ' // & 'FROM sensors ' // & 'LEFT JOIN sync_sensors ON sync_sensors.sensor_id = sensors.sensor_id ' // & 'WHERE sync_sensors.sensor_id IS NULL OR sync_sensors.code NOT IN (201, 409)' @@ -1056,7 +1058,7 @@ module dm_sql 'targets.id, ' // & 'sync_targets.timestamp, ' // & 'sync_targets.code, ' // & - 'sync_targets.nattempts ' // & + 'sync_targets.attempts ' // & 'FROM targets ' // & 'LEFT JOIN sync_targets ON sync_targets.target_id = targets.target_id ' // & 'WHERE sync_targets.target_id IS NULL OR sync_targets.code NOT IN (201, 409)' diff --git a/src/dm_sync.f90 b/src/dm_sync.f90 index e66091e..5ba1f8e 100644 --- a/src/dm_sync.f90 +++ b/src/dm_sync.f90 @@ -31,7 +31,7 @@ module dm_sync character(len=SYNC_ID_LEN) :: id = ' ' !! Sync data id. character(len=TIME_LEN) :: timestamp = TIME_DEFAULT !! Timestamp of last synchronisation attempt. integer :: code = 0 !! HTTP response code of DMPACK server. - integer :: nattempts = 0 !! Number of (unsuccessful) attempts to transfer. + integer :: attempts = 0 !! Number of (unsuccessful) attempts to transfer. end type sync_type integer, parameter, public :: SYNC_SIZE = storage_size(sync_type()) / 8 !! Size of `sync_type` in bytes. @@ -60,7 +60,7 @@ pure elemental logical function dm_sync_equals(sync1, sync2) result(equals) if (sync1%id /= sync2%id) return if (sync1%timestamp /= sync2%timestamp) return if (sync1%code /= sync2%code) return - if (sync1%nattempts /= sync2%nattempts) return + if (sync1%attempts /= sync2%attempts) return equals = .true. end function dm_sync_equals @@ -134,6 +134,6 @@ subroutine dm_sync_out(sync, unit) write (unit_, '("sync.id: ", a)') trim(sync%id) write (unit_, '("sync.timestamp: ", a)') sync%timestamp write (unit_, '("sync.code: ", i0)') sync%code - write (unit_, '("sync.nattempts: ", i0)') sync%nattempts + write (unit_, '("sync.attempts: ", i0)') sync%attempts end subroutine dm_sync_out end module dm_sync diff --git a/src/dm_test.f90 b/src/dm_test.f90 index f912d40..4c4a7a5 100644 --- a/src/dm_test.f90 +++ b/src/dm_test.f90 @@ -166,6 +166,7 @@ impure elemental subroutine dm_test_dummy_observ(observ, id, node_id, sensor_id, observ%sensor_id = 'dummy-sensor' observ%target_id = 'dummy-target' observ%name = 'dummy-observ' + observ%source = 'dmdummy' observ%timestamp = dm_time_now() observ%path = '/dev/null' diff --git a/test/dmtestcsv.f90 b/test/dmtestcsv.f90 index 20b23b1..8b90569 100644 --- a/test/dmtestcsv.f90 +++ b/test/dmtestcsv.f90 @@ -133,7 +133,7 @@ logical function test03() result(stat) end do close (fu) - call dm_perror(rc) + call dm_error_out(rc) if (dm_is_error(rc)) return print *, 'Validating observations ...' @@ -200,7 +200,7 @@ logical function test04() result(stat) close (fu) - call dm_perror(rc) + call dm_error_out(rc) if (dm_is_error(rc)) return print *, 'Validating log ...' @@ -221,7 +221,7 @@ logical function test05() result(stat) integer, parameter :: LEN_DP = 4 !! Data points header length. integer, parameter :: LEN_LOG = 71 !! Logs header length. integer, parameter :: LEN_NODE = 19 !! Nodes header length. - integer, parameter :: LEN_OBSERV = 21954 !! Observations header length. + integer, parameter :: LEN_OBSERV = 21961 !! Observations header length. integer, parameter :: LEN_VIEW = 167 !! Observation views header length. integer, parameter :: LEN_SENSOR = 35 !! Sensors header length. integer, parameter :: LEN_TARGET = 25 !! Targets header length. diff --git a/test/dmtestdb.f90 b/test/dmtestdb.f90 index 72e3dce..29d011d 100644 --- a/test/dmtestdb.f90 +++ b/test/dmtestdb.f90 @@ -341,7 +341,7 @@ logical function test04() result(stat) id = observ%id, & timestamp = dm_time_now(), & code = 500, & - nattempts = 1) + attempts = 1) print *, 'Inserting sync ...' rc = dm_db_insert_sync_observ(db, sync1) diff --git a/test/dmtestjson.f90 b/test/dmtestjson.f90 index b089064..7037ef9 100644 --- a/test/dmtestjson.f90 +++ b/test/dmtestjson.f90 @@ -163,16 +163,16 @@ end function test06 logical function test07() result(stat) character(len=*), parameter :: JSON = & '{ "id": "9273ab62f9a349b6a4da6dd274ee83e7", "node_id": "dummy-node", "sensor_id": "dummy-sensor", ' // & - '"target_id": "dummy-target", "name": "dummy-observ", "timestamp": "1970-01-01T00:00:00.000000+00:00", "path": ' // & - '"/dev/null", "priority": 0, "error": 0, "next": 0, "nreceivers": 3, "nrequests": 2, "receivers": [ ' // & - '"dummy-receiver1", "dummy-receiver2", "dummy-receiver3" ], "requests": [ { "timestamp": ' // & - '"1970-01-01T00:00:00.000000+00:00", "request": "A", "response": "123.45\\r\\n", "delimiter": "\\r\\n", ' // & - '"pattern": "^(.*)$", "delay": 1000, "error": 0, "mode": 0, "retries": 0, "state": 0, "timeout": 500, ' // & - '"nresponses": 1, "responses": [ { "name": "a", "unit": "none", "type": 0, "error": 0, "value": ' // & - '123.450000000 } ] }, { "timestamp": "1970-01-01T00:00:00.000000+00:00", "request": "B", "response": ' // & - '"OK\\r\\n", "delimiter": "\\r\\n", "pattern": "^OK", "delay": 500, "error": 1, "mode": 0, "retries": 0, ' // & - '"state": 0, "timeout": 500, "nresponses": 1, "responses": [ { "name": "b", "unit": "none", "type": 0, ' // & - '"error": 0, "value": 0.990000000000 } ] } ] }' + '"target_id": "dummy-target", "name": "dummy-observ", "source": "dmdummy", "timestamp": ' // & + '"1970-01-01T00:00:00.000000+00:00", "path": "/dev/null", "priority": 0, "error": 0, "next": 0, ' // & + '"nreceivers": 3, "nrequests": 2, "receivers": [ "dummy-receiver1", "dummy-receiver2", "dummy-receiver3" ], ' // & + '"requests": [ { "timestamp": "1970-01-01T00:00:00.000000+00:00", "request": "A", "response": ' // & + '"123.45\\r\\n", "delimiter": "\\r\\n", "pattern": "^(.*)$", "delay": 1000, "error": 0, "mode": 0, ' // & + '"retries": 0, "state": 0, "timeout": 500, "nresponses": 1, "responses": [ { "name": "a", "unit": "none", ' // & + '"type": 0, "error": 0, "value": 123.450000000 } ] }, { "timestamp": "1970-01-01T00:00:00.000000+00:00", ' // & + '"request": "B", "response": "OK\\r\\n", "delimiter": "\\r\\n", "pattern": "^OK", "delay": 500, ' // & + '"error": 1, "mode": 0, "retries": 0, "state": 0, "timeout": 500, "nresponses": 1, "responses": ' // & + '[ { "name": "b", "unit": "none", "type": 0, "error": 0, "value": 0.990000000000 } ] } ] }' character(len=:), allocatable :: buf integer :: rc @@ -190,8 +190,9 @@ logical function test07() result(stat) observ%sensor_id = 'dummy-sensor' observ%target_id = 'dummy-target' observ%name = 'dummy-observ' - observ%path = '/dev/null' + observ%source = 'dmdummy' observ%timestamp = TIME_DEFAULT + observ%path = '/dev/null' print *, 'Adding receivers ...' rc = dm_observ_add_receiver(observ, 'dummy-receiver1')