From 7038ad35ca842d09ee63bb0641454ebd90d19646 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sun, 4 Aug 2024 20:53:50 +0200 Subject: [PATCH] Refactoring of longitude, latitude, and altitude. Updated database schema. --- app/dmdbctl.f90 | 65 +++++++----- app/dmweb.f90 | 76 ++++++++++---- guide/guide.adoc | 137 ++++++++++++++++-------- share/dmweb/dmpack.js | 2 +- src/dm_csv.f90 | 96 ++++++++++------- src/dm_db.f90 | 154 +++++++++++++++------------ src/dm_geojson.f90 | 122 +++++++++++----------- src/dm_hdf5.f90 | 42 ++++++-- src/dm_html.f90 | 24 +++-- src/dm_json.f90 | 28 +++-- src/dm_nml.f90 | 4 +- src/dm_node.f90 | 42 ++++---- src/dm_sensor.f90 | 24 +++-- src/dm_sql.f90 | 238 +++++++++++++++++++++++------------------- src/dm_target.f90 | 35 +++++-- src/dm_test.f90 | 18 ++-- src/dm_util.f90 | 1 - test/dmtestcsv.f90 | 14 ++- test/dmtestjson.f90 | 36 ++++--- 19 files changed, 702 insertions(+), 456 deletions(-) diff --git a/app/dmdbctl.f90 b/app/dmdbctl.f90 index 7381a29..7f537fe 100644 --- a/app/dmdbctl.f90 +++ b/app/dmdbctl.f90 @@ -303,14 +303,14 @@ integer function db_update(db, app) result(rc) if (dm_is_error(rc)) exit db_select ! Overwrite if not passed. - if (.not. app%mask(ATTR_NAME)) app%node%name = old_node%name - if (.not. app%mask(ATTR_META)) app%node%meta = old_node%meta - if (.not. app%mask(ATTR_X)) app%node%x = old_node%x - if (.not. app%mask(ATTR_Y)) app%node%y = old_node%y - if (.not. app%mask(ATTR_Z)) app%node%z = old_node%z - if (.not. app%mask(ATTR_LON)) app%node%longitude = old_node%longitude - if (.not. app%mask(ATTR_LAT)) app%node%latitude = old_node%latitude - if (.not. app%mask(ATTR_ALT)) app%node%altitude = old_node%altitude + if (.not. app%mask(ATTR_NAME)) app%node%name = old_node%name + if (.not. app%mask(ATTR_META)) app%node%meta = old_node%meta + if (.not. app%mask(ATTR_X)) app%node%x = old_node%x + if (.not. app%mask(ATTR_Y)) app%node%y = old_node%y + if (.not. app%mask(ATTR_Z)) app%node%z = old_node%z + if (.not. app%mask(ATTR_LON)) app%node%lon = old_node%lon + if (.not. app%mask(ATTR_LAT)) app%node%lat = old_node%lat + if (.not. app%mask(ATTR_ALT)) app%node%alt = old_node%alt rc = dm_db_update(db, app%node) @@ -336,6 +336,9 @@ integer function db_update(db, app) result(rc) if (.not. app%mask(ATTR_X)) app%sensor%x = old_sensor%x if (.not. app%mask(ATTR_Y)) app%sensor%y = old_sensor%y if (.not. app%mask(ATTR_Z)) app%sensor%z = old_sensor%z + if (.not. app%mask(ATTR_LON)) app%sensor%lon = old_sensor%lon + if (.not. app%mask(ATTR_LAT)) app%sensor%lat = old_sensor%lat + if (.not. app%mask(ATTR_ALT)) app%sensor%alt = old_sensor%alt if (len_trim(app%sensor%node_id) == 0) then rc = E_INVALID @@ -371,6 +374,9 @@ integer function db_update(db, app) result(rc) if (.not. app%mask(ATTR_X)) app%target%x = old_target%x if (.not. app%mask(ATTR_Y)) app%target%y = old_target%y if (.not. app%mask(ATTR_Z)) app%target%z = old_target%z + if (.not. app%mask(ATTR_LON)) app%target%lon = old_target%lon + if (.not. app%mask(ATTR_LAT)) app%target%lat = old_target%lat + if (.not. app%mask(ATTR_ALT)) app%target%alt = old_target%alt rc = dm_db_update(db, app%target) end select db_select @@ -413,9 +419,9 @@ integer function read_args(app) result(rc) arg_type('x', short='X', type=ARG_TYPE_REAL), & ! -X, --x arg_type('y', short='Y', type=ARG_TYPE_REAL), & ! -Y, --y arg_type('z', short='Z', type=ARG_TYPE_REAL), & ! -Z, --z - arg_type('longitude', short='G', type=ARG_TYPE_REAL), & ! -G, --longitude - arg_type('latitude', short='L', type=ARG_TYPE_REAL), & ! -L, --latitude - arg_type('altitude', short='A', type=ARG_TYPE_REAL), & ! -A, --altitude + arg_type('lon', short='G', type=ARG_TYPE_REAL), & ! -G, --lon + arg_type('lat', short='L', type=ARG_TYPE_REAL), & ! -L, --lat + arg_type('alt', short='A', type=ARG_TYPE_REAL), & ! -A, --alt arg_type('verbose', short='V', type=ARG_TYPE_LOGICAL) & ! -V, --verbose ] @@ -448,14 +454,14 @@ integer function read_args(app) result(rc) case (TYPE_NODE) ! Get node attributes. rc = dm_arg_get(args( 6), app%node%id) - rc = dm_arg_get(args( 7), app%node%name, passed=app%mask(ATTR_NAME)) - rc = dm_arg_get(args( 8), app%node%meta, passed=app%mask(ATTR_META)) - rc = dm_arg_get(args(13), app%node%x, passed=app%mask(ATTR_X)) - rc = dm_arg_get(args(14), app%node%y, passed=app%mask(ATTR_Y)) - rc = dm_arg_get(args(15), app%node%z, passed=app%mask(ATTR_Z)) - rc = dm_arg_get(args(16), app%node%longitude, passed=app%mask(ATTR_LON)) - rc = dm_arg_get(args(17), app%node%latitude, passed=app%mask(ATTR_LAT)) - rc = dm_arg_get(args(18), app%node%altitude, passed=app%mask(ATTR_ALT)) + rc = dm_arg_get(args( 7), app%node%name, passed=app%mask(ATTR_NAME)) + rc = dm_arg_get(args( 8), app%node%meta, passed=app%mask(ATTR_META)) + rc = dm_arg_get(args(13), app%node%x, passed=app%mask(ATTR_X)) + rc = dm_arg_get(args(14), app%node%y, passed=app%mask(ATTR_Y)) + rc = dm_arg_get(args(15), app%node%z, passed=app%mask(ATTR_Z)) + rc = dm_arg_get(args(16), app%node%lon, passed=app%mask(ATTR_LON)) + rc = dm_arg_get(args(17), app%node%lat, passed=app%mask(ATTR_LAT)) + rc = dm_arg_get(args(18), app%node%alt, passed=app%mask(ATTR_ALT)) case (TYPE_SENSOR) ! Get sensor attributes. @@ -468,6 +474,9 @@ integer function read_args(app) result(rc) rc = dm_arg_get(args(13), app%sensor%x, passed=app%mask(ATTR_X)) rc = dm_arg_get(args(14), app%sensor%y, passed=app%mask(ATTR_Y)) rc = dm_arg_get(args(15), app%sensor%z, passed=app%mask(ATTR_Z)) + rc = dm_arg_get(args(16), app%sensor%lon, passed=app%mask(ATTR_LON)) + rc = dm_arg_get(args(17), app%sensor%lat, passed=app%mask(ATTR_LAT)) + rc = dm_arg_get(args(18), app%sensor%alt, passed=app%mask(ATTR_ALT)) app%sensor%type = dm_sensor_type_from_name(sensor) @@ -480,6 +489,9 @@ integer function read_args(app) result(rc) rc = dm_arg_get(args(13), app%target%x, passed=app%mask(ATTR_X)) rc = dm_arg_get(args(14), app%target%y, passed=app%mask(ATTR_Y)) rc = dm_arg_get(args(15), app%target%z, passed=app%mask(ATTR_Z)) + rc = dm_arg_get(args(16), app%target%lon, passed=app%mask(ATTR_LON)) + rc = dm_arg_get(args(17), app%target%lat, passed=app%mask(ATTR_LAT)) + rc = dm_arg_get(args(18), app%target%alt, passed=app%mask(ATTR_ALT)) case default rc = E_INVALID @@ -515,17 +527,19 @@ integer function read_args(app) result(rc) .not. app%mask(ATTR_X) .and. .not. app%mask(ATTR_Y) .and. & .not. app%mask(ATTR_Z) .and. .not. app%mask(ATTR_LON) .and. & .not. app%mask(ATTR_LAT) .and. .not. app%mask(ATTR_ALT)) then - call dm_error_out(rc, 'command-line option --name, --meta, -x, -y, -z, ' // & - '--longitude, --latitude, or --altitude required') + call dm_error_out(rc, 'command-line option --name, --meta, --x, --y, --z, ' // & + '--lon, --lat, or --alt required') return end if case (TYPE_TARGET) if (.not. app%mask(ATTR_NAME) .and. .not. app%mask(ATTR_META) .and. & .not. app%mask(ATTR_STATE) .and. .not. app%mask(ATTR_X) .and. & - .not. app%mask(ATTR_Y) .and. .not. app%mask(ATTR_Z)) then - call dm_error_out(rc, 'command-line option --name, --meta, --state, -x, -y, -z, ' // & - '--longitude, --latitude, or --altitude required') + .not. app%mask(ATTR_Y) .and. .not. app%mask(ATTR_Z) .and. & + .not. app%mask(ATTR_LON) .and. .not. app%mask(ATTR_LAT) .and. & + .not. app%mask(ATTR_ALT)) then + call dm_error_out(rc, 'command-line option --name, --meta, --state, --x, --y, --z, ' // & + '--lon, --lat, or --alt required') return end if @@ -537,12 +551,13 @@ integer function read_args(app) result(rc) if (.not. any(app%mask)) then call dm_error_out(rc, 'command-line option --node, --type, --name, --sn, ' // & - '--meta, --easting, --northing, or --altitude required') + '--meta, --x, --y, --z, --lon, --lat, or --alt required') return end if end select end select + ! Validation passed. rc = E_NONE end function read_args end program dmdbctl diff --git a/app/dmweb.f90 b/app/dmweb.f90 index f8b40e0..8342983 100644 --- a/app/dmweb.f90 +++ b/app/dmweb.f90 @@ -716,7 +716,7 @@ subroutine route_map(env) character(len=*), parameter :: JS_DMPACK = APP_JS_PATH // '/dmpack.js' !! DMPACK JS. character(len=*), parameter :: JS_LEAFLET = APP_JS_PATH // '/leaflet.js' !! Leaflet JS. character(len=*), parameter :: STYLE = APP_CSS_PATH // '/leaflet.min.css' !! Additional CSS file. - character(len=*), parameter :: INLINE = '#map { height: 600px; }' !! Inline CSS. + character(len=*), parameter :: INLINE = '#map { height: 600px; }' // CR_LF !! Inline CSS. character(len=*), parameter :: MAP_ID = 'map' !! HTML element id of map. character(len=*), parameter :: TITLE = 'Map' !! Page title. @@ -734,7 +734,7 @@ subroutine route_map(env) ! GET REQUEST. ! ------------------------------------------------------------------ if (len_trim(tile_url) == 0) then - call html_error('No tile map URL provided.', error=E_NOT_FOUND) + call html_error('No tile map URL provided in environment variable DM_TILE_URL.', error=E_EMPTY) return end if @@ -754,17 +754,19 @@ subroutine route_map(env) lon = 0.0_r8 lat = 0.0_r8 + ! Select view point. if (size(nodes) > 0) then - lon = nodes(1)%longitude - lat = nodes(1)%latitude + lon = nodes(1)%lon + lat = nodes(1)%lat else if (size(sensors) > 0) then - lon = sensors(1)%x - lat = sensors(1)%y + lon = sensors(1)%lon + lat = sensors(1)%lat else if (size(targets) > 0) then - lon = targets(1)%x - lat = targets(1)%y + lon = targets(1)%lon + lat = targets(1)%lat end if + ! Use default coordinates for view point. if (dm_equals(lon, 0.0_r8) .and. dm_equals(lat, 0.0_r8)) then lon = APP_MAP_LON lat = APP_MAP_LAT @@ -931,13 +933,13 @@ subroutine route_nodes(env) end if ! Optional parameters. - rc = dm_cgi_get(param, 'meta', node%meta) - rc = dm_cgi_get(param, 'x', node%x) - rc = dm_cgi_get(param, 'y', node%y) - rc = dm_cgi_get(param, 'z', node%z) - rc = dm_cgi_get(param, 'longitude', node%longitude) - rc = dm_cgi_get(param, 'latitude', node%latitude) - rc = dm_cgi_get(param, 'altitude', node%altitude) + rc = dm_cgi_get(param, 'meta', node%meta) + rc = dm_cgi_get(param, 'x', node%x) + rc = dm_cgi_get(param, 'y', node%y) + rc = dm_cgi_get(param, 'z', node%z) + rc = dm_cgi_get(param, 'lon', node%lon) + rc = dm_cgi_get(param, 'lat', node%lat) + rc = dm_cgi_get(param, 'alt', node%alt) ! Validate node data. if (.not. dm_node_valid(node)) then @@ -1508,6 +1510,9 @@ subroutine route_sensors(env) rc = dm_cgi_get(param, 'x', sensor%x) rc = dm_cgi_get(param, 'y', sensor%y) rc = dm_cgi_get(param, 'z', sensor%z) + rc = dm_cgi_get(param, 'lon', sensor%lon) + rc = dm_cgi_get(param, 'lat', sensor%lat) + rc = dm_cgi_get(param, 'alt', sensor%alt) ! Validate sensor data. if (.not. dm_sensor_valid(sensor)) then @@ -1818,6 +1823,9 @@ subroutine route_targets(env) rc = dm_cgi_get(param, 'x', target%x) rc = dm_cgi_get(param, 'y', target%y) rc = dm_cgi_get(param, 'z', target%z) + rc = dm_cgi_get(param, 'lon', target%lon) + rc = dm_cgi_get(param, 'lat', target%lat) + rc = dm_cgi_get(param, 'alt', target%alt) ! Validate target data. if (.not. dm_target_valid(target)) then @@ -2029,14 +2037,14 @@ function html_form_nodes(disabled) result(html) pattern='[\+\-\.0-9]+', placeholder='Enter Z or elevation (optional)') // & H_DIV_END // & ! end column 2 H_DIV_COL // & ! column 3 - dm_html_label('Longitude', for='longitude') // & - dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='longitude', name='longitude', & + dm_html_label('Longitude', for='lon') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lon', name='lon', & pattern='[\+\-\.0-9]+', placeholder='Enter longitude (optional)') // & - dm_html_label('Latitude', for='latitude') // & - dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='latitude', name='latitude', & + dm_html_label('Latitude', for='lat') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lat', name='lat', & pattern='[\+\-\.0-9]+', placeholder='Enter latitude (optional)') // & - dm_html_label('Altitude', for='altitude') // & - dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='altitude', name='altitude', & + dm_html_label('Altitude', for='alt') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='alt', name='alt', & pattern='[\+\-\.0-9]+', placeholder='Enter altitude (optional)') // & H_DIV_END // & ! end column 3 H_DIV_END // & ! end row 1 @@ -2321,8 +2329,19 @@ function html_form_sensors(nodes, disabled) result(html) pattern='[\+\-\.0-9]+', placeholder='Enter Y or northing (optional)') // & dm_html_label('Z', for='z') // & dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='z', name='z', & - pattern='[\+\-\.0-9]+', placeholder='Enter Z or altitude (optional)') // & + pattern='[\+\-\.0-9]+', placeholder='Enter Z or alt (optional)') // & H_DIV_END // & ! end column 3 + H_DIV_COL // & ! column 4 + dm_html_label('Longitude', for='lon') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lon', name='lon', & + pattern='[\+\-\.0-9]+', placeholder='Enter longitude (optional)') // & + dm_html_label('Latitude', for='lat') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lat', name='lat', & + pattern='[\+\-\.0-9]+', placeholder='Enter latitude (optional)') // & + dm_html_label('Altitude', for='alt') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='alt', name='alt', & + pattern='[\+\-\.0-9]+', placeholder='Enter altitude (optional)') // & + H_DIV_END // & ! end column 4 H_DIV_END // & ! end row 1 dm_html_input(HTML_INPUT_TYPE_SUBMIT, disabled=disabled_, name='submit', value='Submit') // & H_FIELDSET_END // H_FORM_END // H_DETAILS_END @@ -2378,8 +2397,19 @@ function html_form_targets(disabled) result(html) pattern='[\+\-\.0-9]+', placeholder='Enter Y or northing (optional)') // & dm_html_label('Z', for='z') // & dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='z', name='z', & - pattern='[\+\-\.0-9]+', placeholder='Enter Z or altitude (optional)') // & + pattern='[\+\-\.0-9]+', placeholder='Enter Z or alt (optional)') // & H_DIV_END // & ! end column 2 + H_DIV_COL // & ! column 3 + dm_html_label('Longitude', for='lon') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lon', name='lon', & + pattern='[\+\-\.0-9]+', placeholder='Enter longitude (optional)') // & + dm_html_label('Latitude', for='lat') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='lat', name='lat', & + pattern='[\+\-\.0-9]+', placeholder='Enter latitude (optional)') // & + dm_html_label('Altitude', for='alt') // & + dm_html_input(HTML_INPUT_TYPE_TEXT, disabled=disabled_, id='alt', name='alt', & + pattern='[\+\-\.0-9]+', placeholder='Enter altitude (optional)') // & + H_DIV_END // & ! end column 3 H_DIV_END // & ! end row 1 dm_html_input(HTML_INPUT_TYPE_SUBMIT, disabled=disabled_, name='submit', value='Submit') // & H_FIELDSET_END // H_FORM_END // H_DETAILS_END diff --git a/guide/guide.adoc b/guide/guide.adoc index c7f1b9a..4670bab 100644 --- a/guide/guide.adoc +++ b/guide/guide.adoc @@ -850,14 +850,14 @@ through command-line arguments. |=== | Option | Short | Default | Description -| `--altitude _alt_` | `-A` | – | Node, sensor, or target altitude (optional). +| `--alt _alt_` | `-A` | – | Node, sensor, or target altitude (optional). | `--create _type_` | `-C` | – | Create record of given type (`node`, `sensor`, or `target`). | `--database _file_` | `-d` | – | Path to SQLite observation database (required). | `--delete _type_` | `-D` | – | Delete record of given type (`node`, `sensor`, or `target`). | `--help` | `-h` | – | Output available command-line arguments and quit. | `--id _id_` | `-I` | – | Node, sensor, or target id (required). -| `--latitude _lat_` | `-L` | – | Node, sensor, or target latitude (optional). -| `--longitude _lon_` | `-G` | – | Node, sensor, or target longitude (optional). +| `--lat _lat_` | `-L` | – | Node, sensor, or target latitude (optional). +| `--lon _lon_` | `-G` | – | Node, sensor, or target longitude (optional). | `--meta _meta_` | `-M` | – | Node, sensor, or target meta description (optional). | `--name _name_` | `-n` | – | Node, sensor, or target name. | `--node _id_` | `-N` | – | Id of node the sensor is associated with. @@ -903,6 +903,9 @@ sensor.meta: dummy sensor sensor.x: 0.000000000000 sensor.y: 0.000000000000 sensor.z: 0.000000000000 +sensor.lon: 0.000000000000 +sensor.lat: 0.000000000000 +sensor.alt: 0.000000000000 .... === dmexport [[dmexport]] @@ -6501,17 +6504,17 @@ LOG%MESSAGE="dummy log message", [cols="3,2,2,14"] |=== -| Attribute | Type | Size | Description +| Attribute | Type | Size | Description -| `id` | string | 32 | Node id (`-0-9A-Z_a-z`). -| `name` | string | 32 | Node name. -| `meta` | string | 32 | Node description (optional). -| `x` | double | 8 | Node local x (optional). -| `y` | double | 8 | Node local y (optional). -| `z` | double | 8 | Node local z (optional). -| `longitude` | double | 8 | Node longitude (optional). -| `latitude` | double | 8 | Node latitude (optional). -| `altitude` | double | 8 | Node altitude (optional). +| `id` | string | 32 | Node id (`-0-9A-Z_a-z`). +| `name` | string | 32 | Node name. +| `meta` | string | 32 | Node description (optional). +| `x` | double | 8 | Node local x (optional). +| `y` | double | 8 | Node local y (optional). +| `z` | double | 8 | Node local z (optional). +| `lon` | double | 8 | Node longitude (optional). +| `lat` | double | 8 | Node latitude (optional). +| `alt` | double | 8 | Node altitude (optional). |=== ==== CSV [[data-node-csv]] @@ -6520,15 +6523,15 @@ LOG%MESSAGE="dummy log message", |=== | Column | Attribute | Description -| 1 | `id` | Node id. -| 2 | `name` | Node name. -| 3 | `meta` | Node description. -| 7 | `x` | Node local x. -| 8 | `y` | Node local y. -| 9 | `z` | Node local z. -| 4 | `longitude` | Node longitude. -| 5 | `latitude` | Node latitude. -| 6 | `altitude` | Node altitude. +| 1 | `id` | Node id. +| 2 | `name` | Node name. +| 3 | `meta` | Node description. +| 7 | `x` | Node local x. +| 8 | `y` | Node local y. +| 9 | `z` | Node local z. +| 4 | `lon` | Node longitude. +| 5 | `lat` | Node latitude. +| 6 | `alt` | Node altitude. |=== ==== GeoJSON [[data-node-geojson]] @@ -6549,9 +6552,9 @@ LOG%MESSAGE="dummy log message", "x": 0.0, "y": 0.0, "z": 0.0, - "longitude": 0.0, - "latitude": 0.0, - "altitude": 0.0 + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } } .... @@ -6582,9 +6585,9 @@ DATASET "node_type" { H5T_IEEE_F64LE "x"; H5T_IEEE_F64LE "y"; H5T_IEEE_F64LE "z"; - H5T_IEEE_F64LE "longitude"; - H5T_IEEE_F64LE "latitude"; - H5T_IEEE_F64LE "altitude"; + H5T_IEEE_F64LE "lon"; + H5T_IEEE_F64LE "lat"; + H5T_IEEE_F64LE "alt"; } DATASPACE SIMPLE { ( 8 ) / ( 8 ) } } @@ -6601,9 +6604,9 @@ DATASET "node_type" { "x": 0.0, "y": 0.0, "z": 0.0, - "longitude": 0.0, - "latitude": 0.0, - "altitude": 0.0 + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } .... @@ -6617,9 +6620,9 @@ NODE%META="Description", NODE%X=0.0, NODE%Y=0.0, NODE%Z=0.0, -NODE%LONGITUDE=0.0, -NODE%LATITUDE=0.0, -NODE%ALTITUDE=0.0 +NODE%LON=0.0, +NODE%LAT=0.0, +NODE%ALT=0.0 / .... @@ -6962,6 +6965,9 @@ OBSERV%REQUESTS(1)%RESPONSES(1)%VALUE=10.00000000000000, | `x` | double | 8 | Sensor x or easting (optional). | `y` | double | 8 | Sensor y or northing (optional). | `z` | double | 8 | Sensor z or altitude (optional). +| `lon` | double | 8 | Sensor longitude (optional). +| `lat` | double | 8 | Sensor latitude (optional). +| `alt` | double | 8 | Sensor altitude (optional). |=== ==== CSV [[data-sensor-csv]] @@ -6979,6 +6985,9 @@ OBSERV%REQUESTS(1)%RESPONSES(1)%VALUE=10.00000000000000, | 7 | `x` | Sensor x or easting. | 8 | `y` | Sensor y or northing. | 9 | `z` | Sensor z or altitude. +| 10 | `lon` | Sensor longitude. +| 11 | `lat` | Sensor latitude. +| 12 | `alt` | Sensor altitude. |=== ==== GeoJSON [[data-sensor-geojson]] @@ -6987,13 +6996,21 @@ OBSERV%REQUESTS(1)%RESPONSES(1)%VALUE=10.00000000000000, .... { "type": "Feature", - "properties": { - "name": "Dummy Sensor", - "popupContent": "Description" - }, "geometry": { "type": "Point", "coordinates": [ 0.0, 0.0, 0.0 ] + }, + "properties": { + "type": "sensor", + "id": "dummy-sensor", + "name": "Dummy Sensor", + "meta": "Description", + "x": 0.0, + "y": 0.0, + "z": 0.0, + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } } .... @@ -7037,6 +7054,9 @@ DATASET "sensor_type" { H5T_IEEE_F64LE "x"; H5T_IEEE_F64LE "y"; H5T_IEEE_F64LE "z"; + H5T_IEEE_F64LE "lon"; + H5T_IEEE_F64LE "lat"; + H5T_IEEE_F64LE "alt"; } DATASPACE SIMPLE { ( 8 ) / ( 8 ) } } @@ -7055,7 +7075,10 @@ DATASET "sensor_type" { "meta": "Description", "x": 0.0, "y": 0.0, - "z": 0.0 + "z": 0.0, + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } .... @@ -7072,6 +7095,9 @@ SENSOR%META="Description", SENSOR%X=0.0, SENSOR%Y=0.0, SENSOR%Z=0.0, +SENSOR%LON=0.0, +SENSOR%LAT=0.0, +SENSOR%ALT=0.0 / .... @@ -7104,6 +7130,9 @@ SENSOR%Z=0.0, | `x` | double | 8 | Target x or easting (optional). | `y` | double | 8 | Target y or northing (optional). | `z` | double | 8 | Target z or altitude (optional). +| `lon` | double | 8 | Target longitude (optional). +| `lat` | double | 8 | Target latitude (optional). +| `alt` | double | 8 | Target altitude (optional). |=== ==== CSV [[data-target-csv]] @@ -7119,6 +7148,9 @@ SENSOR%Z=0.0, | 5 | `x` | Target x or easting. | 6 | `y` | Target y or northing. | 7 | `z` | Target z or altitude. +| 8 | `lon` | Target longitude. +| 9 | `lat` | Target latitude. +| 10 | `alt` | Target altitude. |=== ==== GeoJSON [[data-target-geojson]] @@ -7127,13 +7159,21 @@ SENSOR%Z=0.0, .... { "type": "Feature", - "properties": { - "name": "Dummy Target", - "popupContent": "Description" - }, "geometry": { "type": "Point", "coordinates": [ 0.0, 0.0, 0.0 ] + }, + "properties": { + "type": "target", + "id": "dummy-target", + "name": "Dummy Target", + "meta": "Description", + "x": 0.0, + "y": 0.0, + "z": 0.0, + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } } .... @@ -7165,6 +7205,9 @@ DATASET "target_type" { H5T_IEEE_F64LE "x"; H5T_IEEE_F64LE "y"; H5T_IEEE_F64LE "z"; + H5T_IEEE_F64LE "lon"; + H5T_IEEE_F64LE "lat"; + H5T_IEEE_F64LE "alt"; } DATASPACE SIMPLE { ( 8 ) / ( 8 ) } } @@ -7181,7 +7224,10 @@ DATASET "target_type" { "state": 0, "x": 0.0, "y": 0.0, - "z": 0.0 + "z": 0.0, + "lon": 0.0, + "lat": 0.0, + "alt": 0.0 } .... @@ -7195,6 +7241,9 @@ TARGET%STATE=0, TARGET%X=0.0, TARGET%Y=0.0, TARGET%Z=0.0, +TARGET%LON=0.0, +TARGET%LAT=0.0, +TARGET%ALT=0.0 / .... diff --git a/share/dmweb/dmpack.js b/share/dmweb/dmpack.js index 7a6482a..b43c359 100644 --- a/share/dmweb/dmpack.js +++ b/share/dmweb/dmpack.js @@ -1,4 +1,4 @@ -/*jshint esversion: 6 */ +/* jshint esversion: 6 */ /** * Creates map with Leaflet. diff --git a/src/dm_csv.f90 b/src/dm_csv.f90 index 299d345..aef65ce 100644 --- a/src/dm_csv.f90 +++ b/src/dm_csv.f90 @@ -13,6 +13,8 @@ module dm_csv character, parameter, public :: CSV_SEPARATOR = ',' !! Default CSV field separator. integer, parameter, public :: CSV_BUFFER_LEN = 8192 !! CSV line buffer length. + character(len=*), parameter :: FMT_REAL = '1pg0.12' + interface dm_csv_from !! Generic derived type to CSV serialisation function. module procedure :: csv_from_beat @@ -201,15 +203,15 @@ function dm_csv_header_node(separator) result(header) s = CSV_SEPARATOR if (present(separator)) s = separator - header = '#id' // s // & - 'name' // s // & - 'meta' // s // & - 'x' // s // & - 'y' // s // & - 'z' // s // & - 'longitude' // s // & - 'latitude' // s // & - 'altitude' + header = '#id' // s // & + 'name' // s // & + 'meta' // s // & + 'x' // s // & + 'y' // s // & + 'z' // s // & + 'lon' // s // & + 'lat' // s // & + 'alt' end function dm_csv_header_node function dm_csv_header_observ(separator) result(header) @@ -318,7 +320,10 @@ function dm_csv_header_sensor(separator) result(header) 'meta' // s // & 'x' // s // & 'y' // s // & - 'z' + 'z' // s // & + 'lon' // s // & + 'lat' // s // & + 'alt' end function dm_csv_header_sensor function dm_csv_header_target(separator) result(header) @@ -338,7 +343,10 @@ function dm_csv_header_target(separator) result(header) 'state' // s // & 'x' // s // & 'y' // s // & - 'z' + 'z' // s // & + 'lon' // s // & + 'lat' // s // & + 'alt' end function dm_csv_header_target ! ****************************************************************** @@ -516,9 +524,9 @@ function csv_from_node(node, separator) result(csv) dm_ftoa(node%x) // s // & dm_ftoa(node%y) // s // & dm_ftoa(node%z) // s // & - dm_ftoa(node%longitude) // s // & - dm_ftoa(node%latitude) // s // & - dm_ftoa(node%altitude) + dm_ftoa(node%lon) // s // & + dm_ftoa(node%lat) // s // & + dm_ftoa(node%alt) end function csv_from_node function csv_from_nodes(nodes, header, separator) result(csv) @@ -732,7 +740,10 @@ function csv_from_sensor(sensor, separator) result(csv) '"' // trim(sensor%meta) // '"' // s // & dm_ftoa(sensor%x) // s // & dm_ftoa(sensor%y) // s // & - dm_ftoa(sensor%z) + dm_ftoa(sensor%z) // s // & + dm_ftoa(sensor%lon) // s // & + dm_ftoa(sensor%lat) // s // & + dm_ftoa(sensor%alt) end function csv_from_sensor function csv_from_sensors(sensors, header, separator) result(csv) @@ -784,7 +795,10 @@ function csv_from_target(target, separator) result(csv) dm_itoa(target%state) // s // & dm_ftoa(target%x) // s // & dm_ftoa(target%y) // s // & - dm_ftoa(target%z) + dm_ftoa(target%z) // s // & + dm_ftoa(target%lon) // s // & + dm_ftoa(target%lat) // s // & + dm_ftoa(target%alt) end function csv_from_target function csv_from_targets(targets, header, separator) result(csv) @@ -1055,15 +1069,15 @@ integer function csv_read_node(node, unit, separator, quote) result(rc) p = 0 ! Cursor in buffer string. - rc = csv_next(buffer, node%id, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%name, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%meta, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%x, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%y, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%z, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%longitude, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%latitude, s, n, p, q); if (rc /= E_NONE) return - rc = csv_next(buffer, node%altitude, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%id, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%name, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%meta, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%x, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%y, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%z, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%lon, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%lat, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, node%alt, s, n, p, q); if (rc /= E_NONE) return rc = E_NONE end function csv_read_node @@ -1207,6 +1221,9 @@ integer function csv_read_sensor(sensor, unit, separator, quote) result(rc) rc = csv_next(buffer, sensor%x, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, sensor%y, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, sensor%z, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, sensor%lon, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, sensor%lat, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, sensor%alt, s, n, p, q); if (rc /= E_NONE) return rc = E_NONE end function csv_read_sensor @@ -1259,6 +1276,9 @@ integer function csv_read_target(target, unit, separator, quote) result(rc) rc = csv_next(buffer, target%x, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, target%y, s, n, p, q); if (rc /= E_NONE) return rc = csv_next(buffer, target%z, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, target%lon, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, target%lat, s, n, p, q); if (rc /= E_NONE) return + rc = csv_next(buffer, target%alt, s, n, p, q); if (rc /= E_NONE) return rc = E_NONE end function csv_read_target @@ -1366,7 +1386,7 @@ integer function csv_write_data_point(data_point, unit, header, separator) resul if (stat /= 0) return end if - write (unit_, '(a29, a1, 1pg0.12)', iostat=stat) data_point%x, s, data_point%y + write (unit_, '(a29, a1, ' // FMT_REAL // ')', iostat=stat) data_point%x, s, data_point%y if (stat /= 0) return rc = E_NONE @@ -1508,16 +1528,16 @@ integer function csv_write_node(node, unit, header, separator) result(rc) if (stat /= 0) return end if - write (unit_, '(7a, 6(a, 1pg0.12))', iostat=stat) & + write (unit_, '(7a, 6(a, ' // FMT_REAL // '))', iostat=stat) & trim(node%id), s, & trim(node%name), s, & '"', trim(node%meta), '"', s, & node%x, s, & node%y, s, & node%z, s, & - node%longitude, s, & - node%latitude, s, & - node%altitude + node%lon, s, & + node%lat, s, & + node%alt if (stat /= 0) return rc = E_NONE @@ -1643,7 +1663,7 @@ integer function csv_write_observ(observ, unit, header, separator) result(rc) write (unit_, '(a)', advance='no', iostat=stat) s if (stat /= 0) return - write (unit_, '(4a, 2(i0, a), 1pg0.12)', advance='no', iostat=stat) & + write (unit_, '(4a, 2(i0, a), ' // FMT_REAL // ')', advance='no', iostat=stat) & trim(observ%requests(i)%responses(j)%name), s, & trim(observ%requests(i)%responses(j)%unit), s, & observ%requests(i)%responses(j)%type, s, & @@ -1718,7 +1738,7 @@ integer function csv_write_sensor(sensor, unit, header, separator) result(rc) if (stat /= 0) return end if - write (unit_, '(4a, i0, 8a, 3(a, 1pg0.12))', iostat=stat) & + write (unit_, '(4a, i0, 8a, 6(a, ' // FMT_REAL // '))', iostat=stat) & trim(sensor%id), s, & trim(sensor%node_id), s, & sensor%type, s, & @@ -1727,7 +1747,10 @@ integer function csv_write_sensor(sensor, unit, header, separator) result(rc) '"', trim(sensor%meta), '"', s, & sensor%x, s, & sensor%y, s, & - sensor%z + sensor%z, s, & + sensor%lon, s, & + sensor%lat, s, & + sensor%alt if (stat /= 0) return rc = E_NONE @@ -1788,14 +1811,17 @@ integer function csv_write_target(target, unit, header, separator) result(rc) s = CSV_SEPARATOR if (present(separator)) s = separator - write (unit_, '(8a, i0, 3(a, 1pg0.12))', iostat=stat) & + write (unit_, '(8a, i0, 6(a, ' // FMT_REAL // '))', iostat=stat) & trim(target%id), s, & trim(target%name), s, & '"', trim(target%meta), '"', s, & target%state, s, & target%x, s, & target%y, s, & - target%z + target%z, s, & + target%lon, s, & + target%lat, s, & + target%alt if (stat /= 0) return rc = E_NONE diff --git a/src/dm_db.f90 b/src/dm_db.f90 index a575658..d0318ba 100644 --- a/src/dm_db.f90 +++ b/src/dm_db.f90 @@ -1672,9 +1672,9 @@ integer function dm_db_insert_node(db, node, validate) result(rc) if (sqlite3_bind_double(stmt, 4, node%x) /= SQLITE_OK) exit sql_block if (sqlite3_bind_double(stmt, 5, node%y) /= SQLITE_OK) exit sql_block if (sqlite3_bind_double(stmt, 6, node%z) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 7, node%longitude) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 8, node%latitude) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 9, node%altitude) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, node%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, node%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 9, node%alt) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -1902,15 +1902,18 @@ integer function dm_db_insert_sensor(db, sensor, validate) result(rc) if (sqlite3_prepare_v2(db%ptr, SQL_INSERT_SENSOR, stmt) /= SQLITE_OK) exit sql_block rc = E_DB_BIND - if (sqlite3_bind_text (stmt, 1, trim(sensor%id)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 2, trim(sensor%node_id)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 3, sensor%type) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 4, trim(sensor%name)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 5, trim(sensor%sn)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 6, trim(sensor%meta)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 7, sensor%x) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 8, sensor%y) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 9, sensor%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 1, trim(sensor%id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 2, trim(sensor%node_id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 3, sensor%type) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 4, trim(sensor%name)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 5, trim(sensor%sn)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 6, trim(sensor%meta)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, sensor%x) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, sensor%y) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 9, sensor%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 10, sensor%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 11, sensor%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 12, sensor%alt) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -2097,13 +2100,16 @@ integer function dm_db_insert_target(db, target, validate) result(rc) if (sqlite3_prepare_v2(db%ptr, SQL_INSERT_TARGET, stmt) /= SQLITE_OK) exit sql_block rc = E_DB_BIND - if (sqlite3_bind_text (stmt, 1, trim(target%id)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 2, trim(target%name)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 3, trim(target%meta)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 4, target%state) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 5, target%x) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 6, target%y) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 7, target%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 1, trim(target%id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 2, trim(target%name)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 3, trim(target%meta)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 4, target%state) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 5, target%x) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 6, target%y) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, target%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, target%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 9, target%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 10, target%alt) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -3905,9 +3911,9 @@ integer function dm_db_update_node(db, node, validate) result(rc) if (sqlite3_bind_double(stmt, 3, node%x) /= SQLITE_OK) exit sql_block if (sqlite3_bind_double(stmt, 4, node%y) /= SQLITE_OK) exit sql_block if (sqlite3_bind_double(stmt, 5, node%z) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 6, node%longitude) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 7, node%latitude) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 8, node%altitude) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 6, node%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, node%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, node%alt) /= SQLITE_OK) exit sql_block if (sqlite3_bind_text (stmt, 9, trim(node%id)) /= SQLITE_OK) exit sql_block rc = E_DB_STEP @@ -3959,15 +3965,18 @@ integer function dm_db_update_sensor(db, sensor, validate) result(rc) rc = E_DB_BIND ! Sensor id must be last argument! - if (sqlite3_bind_text (stmt, 1, trim(sensor%node_id)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 2, sensor%type) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 3, trim(sensor%name)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 4, trim(sensor%sn)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 5, trim(sensor%meta)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 6, sensor%x) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 7, sensor%y) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 8, sensor%z) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 9, trim(sensor%id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 1, trim(sensor%node_id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 2, sensor%type) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 3, trim(sensor%name)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 4, trim(sensor%sn)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 5, trim(sensor%meta)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 6, sensor%x) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, sensor%y) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, sensor%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 9, sensor%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 10, sensor%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 11, sensor%alt) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 12, trim(sensor%id)) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -4018,13 +4027,16 @@ integer function dm_db_update_target(db, target, validate) result(rc) rc = E_DB_BIND ! Target id must be last argument! - if (sqlite3_bind_text (stmt, 1, trim(target%name)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 2, trim(target%meta)) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_int (stmt, 3, target%state) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 4, target%x) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 5, target%y) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_double(stmt, 6, target%z) /= SQLITE_OK) exit sql_block - if (sqlite3_bind_text (stmt, 7, trim(target%id)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 1, trim(target%name)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 2, trim(target%meta)) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_int (stmt, 3, target%state) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 4, target%x) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 5, target%y) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 6, target%z) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 7, target%lon) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 8, target%lat) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_double(stmt, 9, target%alt) /= SQLITE_OK) exit sql_block + if (sqlite3_bind_text (stmt, 10, trim(target%id)) /= SQLITE_OK) exit sql_block rc = E_DB_STEP if (sqlite3_step(stmt) /= SQLITE_DONE) exit sql_block @@ -4845,15 +4857,15 @@ integer function db_next_row_node(stmt, node, validate) result(rc) if (sqlite3_column_type(stmt, 8) /= SQLITE_FLOAT) return end if - node%id = sqlite3_column_text (stmt, 0) - node%name = sqlite3_column_text (stmt, 1) - node%meta = sqlite3_column_text (stmt, 2) - node%x = sqlite3_column_double(stmt, 3) - node%y = sqlite3_column_double(stmt, 4) - node%z = sqlite3_column_double(stmt, 5) - node%longitude = sqlite3_column_double(stmt, 6) - node%latitude = sqlite3_column_double(stmt, 7) - node%altitude = sqlite3_column_double(stmt, 8) + node%id = sqlite3_column_text (stmt, 0) + node%name = sqlite3_column_text (stmt, 1) + node%meta = sqlite3_column_text (stmt, 2) + node%x = sqlite3_column_double(stmt, 3) + node%y = sqlite3_column_double(stmt, 4) + node%z = sqlite3_column_double(stmt, 5) + node%lon = sqlite3_column_double(stmt, 6) + node%lat = sqlite3_column_double(stmt, 7) + node%alt = sqlite3_column_double(stmt, 8) rc = E_NONE end function db_next_row_node @@ -4972,26 +4984,32 @@ integer function db_next_row_sensor(stmt, sensor, validate) result(rc) if (validate_) then rc = E_DB_TYPE - if (sqlite3_column_type(stmt, 0) /= SQLITE_TEXT) return - if (sqlite3_column_type(stmt, 1) /= SQLITE_TEXT) return - if (sqlite3_column_type(stmt, 2) /= SQLITE_INTEGER) return - if (sqlite3_column_type(stmt, 3) /= SQLITE_TEXT) return - 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_FLOAT) return - if (sqlite3_column_type(stmt, 7) /= SQLITE_FLOAT) return - if (sqlite3_column_type(stmt, 8) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 0) /= SQLITE_TEXT) return + if (sqlite3_column_type(stmt, 1) /= SQLITE_TEXT) return + if (sqlite3_column_type(stmt, 2) /= SQLITE_INTEGER) return + if (sqlite3_column_type(stmt, 3) /= SQLITE_TEXT) return + 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_FLOAT) return + if (sqlite3_column_type(stmt, 7) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 8) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 9) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 10) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 11) /= SQLITE_FLOAT) return end if - sensor%id = sqlite3_column_text (stmt, 0) - sensor%node_id = sqlite3_column_text (stmt, 1) - sensor%type = sqlite3_column_int (stmt, 2) - sensor%name = sqlite3_column_text (stmt, 3) - sensor%sn = sqlite3_column_text (stmt, 4) - sensor%meta = sqlite3_column_text (stmt, 5) - sensor%x = sqlite3_column_double(stmt, 6) - sensor%y = sqlite3_column_double(stmt, 7) - sensor%z = sqlite3_column_double(stmt, 8) + sensor%id = sqlite3_column_text (stmt, 0) + sensor%node_id = sqlite3_column_text (stmt, 1) + sensor%type = sqlite3_column_int (stmt, 2) + sensor%name = sqlite3_column_text (stmt, 3) + sensor%sn = sqlite3_column_text (stmt, 4) + sensor%meta = sqlite3_column_text (stmt, 5) + sensor%x = sqlite3_column_double(stmt, 6) + sensor%y = sqlite3_column_double(stmt, 7) + sensor%z = sqlite3_column_double(stmt, 8) + sensor%lon = sqlite3_column_double(stmt, 9) + sensor%lat = sqlite3_column_double(stmt, 10) + sensor%alt = sqlite3_column_double(stmt, 11) rc = E_NONE end function db_next_row_sensor @@ -5079,6 +5097,9 @@ integer function db_next_row_target(stmt, target, validate) result(rc) if (sqlite3_column_type(stmt, 4) /= SQLITE_FLOAT) return if (sqlite3_column_type(stmt, 5) /= SQLITE_FLOAT) return if (sqlite3_column_type(stmt, 6) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 7) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 8) /= SQLITE_FLOAT) return + if (sqlite3_column_type(stmt, 9) /= SQLITE_FLOAT) return end if target%id = sqlite3_column_text (stmt, 0) @@ -5088,6 +5109,9 @@ integer function db_next_row_target(stmt, target, validate) result(rc) target%x = sqlite3_column_double(stmt, 4) target%y = sqlite3_column_double(stmt, 5) target%z = sqlite3_column_double(stmt, 6) + target%lon = sqlite3_column_double(stmt, 7) + target%lat = sqlite3_column_double(stmt, 8) + target%alt = sqlite3_column_double(stmt, 9) rc = E_NONE end function db_next_row_target diff --git a/src/dm_geojson.f90 b/src/dm_geojson.f90 index 8d343dc..cf5525b 100644 --- a/src/dm_geojson.f90 +++ b/src/dm_geojson.f90 @@ -39,7 +39,7 @@ module dm_geojson ! ****************************************************************** ! PUBLIC PROCEDURES. ! ****************************************************************** - subroutine dm_geojson_feature_point(geojson, type, id, name, meta, x, y, z, longitude, latitude, altitude) + subroutine dm_geojson_feature_point(geojson, type, id, name, meta, x, y, z, lon, lat, alt) !! Returns a GeoJSON string of the following form: !! !! ```json @@ -61,23 +61,23 @@ subroutine dm_geojson_feature_point(geojson, type, id, name, meta, x, y, z, long !! "x": 0.0, !! "y": 0.0, !! "z": 0.0, - !! "longitude": 10.4541194000, - !! "latitude": 51.1642292000, - !! "altitude": 10.0000000000 + !! "lon": 10.4541194000, + !! "lat": 51.1642292000, + !! "alt": 10.0000000000 !! } !! } !! ``` - character(len=:), allocatable, intent(out) :: geojson !! Output GeoJSON string. - integer, intent(in) :: type !! Point type. - character(len=*), intent(in) :: id !! Point id. - character(len=*), intent(in) :: name !! Point name. - character(len=*), intent(in) :: meta !! Point meta data. - real(kind=r8), intent(in) :: x !! Point x. - real(kind=r8), intent(in) :: y !! Point y. - real(kind=r8), intent(in) :: z !! Point z. - real(kind=r8), intent(in) :: longitude !! Point longitude. - real(kind=r8), intent(in) :: latitude !! Point latitude. - real(kind=r8), intent(in) :: altitude !! Point altitude. + character(len=:), allocatable, intent(out) :: geojson !! Output GeoJSON string. + integer, intent(in) :: type !! Point type. + character(len=*), intent(in) :: id !! Point id. + character(len=*), intent(in) :: name !! Point name. + character(len=*), intent(in) :: meta !! Point meta data. + real(kind=r8), intent(in) :: x !! Point x. + real(kind=r8), intent(in) :: y !! Point y. + real(kind=r8), intent(in) :: z !! Point z. + real(kind=r8), intent(in) :: lon !! Point longitude. + real(kind=r8), intent(in) :: lat !! Point latitude. + real(kind=r8), intent(in) :: alt !! Point altitude. integer :: type_ @@ -87,20 +87,18 @@ subroutine dm_geojson_feature_point(geojson, type, id, name, meta, x, y, z, long geojson = & '{"type":"Feature",' // & '"geometry":{"type":"Point",' // '"coordinates":[' // & - dm_ftoa(longitude) // ',' // & - dm_ftoa(latitude) // ',' // & - dm_ftoa(altitude) // ']},' // & - '"properties":{' // & - '"type":"' // trim(TYPE_NAMES(type_)) // '",' // & - '"id":"' // id // '",' // & - '"name":"' // name // '",' // & - '"meta":"' // dm_json_escape(meta) // '",' // & - '"x":' // dm_ftoa(x) // ',' // & - '"y":' // dm_ftoa(y) // ',' // & - '"z":' // dm_ftoa(z) // ',' // & - '"longitude":' // dm_ftoa(longitude) // ',' // & - '"latitude":' // dm_ftoa(latitude) // ',' // & - '"altitude":' // dm_ftoa(altitude) // '}}' + dm_ftoa(lon) // ',' // dm_ftoa(lat) // ',' // dm_ftoa(alt) // & + '"]},properties":{' // & + '"type":"' // trim(TYPE_NAMES(type_)) // '",' // & + '"id":"' // id // '",' // & + '"name":"' // name // '",' // & + '"meta":"' // dm_json_escape(meta) // '",' // & + '"x":' // dm_ftoa(x) // ',' // & + '"y":' // dm_ftoa(y) // ',' // & + '"z":' // dm_ftoa(z) // ',' // & + '"lon":' // dm_ftoa(lon) // ',' // & + '"lat":' // dm_ftoa(lat) // ',' // & + '"alt":' // dm_ftoa(alt) // '}}' end subroutine dm_geojson_feature_point ! ****************************************************************** @@ -113,17 +111,17 @@ function geojson_from_node(node) result(geojson) type(node_type), intent(inout) :: node !! Node type. character(len=:), allocatable :: geojson !! Alloctable GeoJSON string. - call dm_geojson_feature_point(geojson = geojson, & - type = TYPE_NODE, & - id = trim(node%id), & - name = trim(node%name), & - meta = trim(node%meta), & - x = node%x, & - y = node%y, & - z = node%z, & - longitude = node%longitude, & - latitude = node%latitude, & - altitude = node%altitude) + call dm_geojson_feature_point(geojson = geojson, & + type = TYPE_NODE, & + id = trim(node%id), & + name = trim(node%name), & + meta = trim(node%meta), & + x = node%x, & + y = node%y, & + z = node%z, & + lon = node%lon, & + lat = node%lat, & + alt = node%alt) end function geojson_from_node function geojson_from_sensor(sensor) result(geojson) @@ -133,17 +131,17 @@ function geojson_from_sensor(sensor) result(geojson) type(sensor_type), intent(inout) :: sensor !! Sensor type. character(len=:), allocatable :: geojson !! Alloctable GeoJSON string. - call dm_geojson_feature_point(geojson = geojson, & - type = TYPE_SENSOR, & - id = trim(sensor%id), & - name = trim(sensor%name), & - meta = trim(sensor%meta), & - x = sensor%x, & - y = sensor%y, & - z = sensor%z, & - longitude = sensor%x, & - latitude = sensor%y, & - altitude = sensor%z) + call dm_geojson_feature_point(geojson = geojson, & + type = TYPE_SENSOR, & + id = trim(sensor%id), & + name = trim(sensor%name), & + meta = trim(sensor%meta), & + x = sensor%x, & + y = sensor%y, & + z = sensor%z, & + lon = sensor%lon, & + lat = sensor%lat, & + alt = sensor%alt) end function geojson_from_sensor function geojson_from_target(target) result(geojson) @@ -153,17 +151,17 @@ function geojson_from_target(target) result(geojson) type(target_type), intent(inout) :: target !! Target type. character(len=:), allocatable :: geojson !! Alloctable GeoJSON string. - call dm_geojson_feature_point(geojson = geojson, & - type = TYPE_TARGET, & - id = trim(target%id), & - name = trim(target%name), & - meta = trim(target%meta), & - x = target%x, & - y = target%y, & - z = target%z, & - longitude = target%x, & - latitude = target%y, & - altitude = target%z) + call dm_geojson_feature_point(geojson = geojson, & + type = TYPE_TARGET, & + id = trim(target%id), & + name = trim(target%name), & + meta = trim(target%meta), & + x = target%x, & + y = target%y, & + z = target%z, & + lon = target%lon, & + lat = target%lat, & + alt = target%alt) end function geojson_from_target integer function geojson_write_node(node, unit) result(rc) diff --git a/src/dm_hdf5.f90 b/src/dm_hdf5.f90 index c27b828..eb1384e 100644 --- a/src/dm_hdf5.f90 +++ b/src/dm_hdf5.f90 @@ -463,18 +463,18 @@ integer function hdf5_create_node(type_id) result(rc) if (stat < 0) return ! Node longitude. - offset = h5offsetof(c_loc(node), c_loc(node%longitude)) - call h5tinsert_f(type_id, 'longitude', offset, h5kind_to_type(kind(node%longitude), H5_REAL_KIND), stat) + offset = h5offsetof(c_loc(node), c_loc(node%lon)) + call h5tinsert_f(type_id, 'lon', offset, h5kind_to_type(kind(node%lon), H5_REAL_KIND), stat) if (stat < 0) return ! Node latitude. - offset = h5offsetof(c_loc(node), c_loc(node%latitude)) - call h5tinsert_f(type_id, 'latitude', offset, h5kind_to_type(kind(node%latitude), H5_REAL_KIND), stat) + offset = h5offsetof(c_loc(node), c_loc(node%lat)) + call h5tinsert_f(type_id, 'lat', offset, h5kind_to_type(kind(node%lat), H5_REAL_KIND), stat) if (stat < 0) return ! Node altitude. - offset = h5offsetof(c_loc(node), c_loc(node%altitude)) - call h5tinsert_f(type_id, 'altitude', offset, h5kind_to_type(kind(node%altitude), H5_REAL_KIND), stat) + offset = h5offsetof(c_loc(node), c_loc(node%alt)) + call h5tinsert_f(type_id, 'alt', offset, h5kind_to_type(kind(node%alt), H5_REAL_KIND), stat) if (stat < 0) return rc = E_NONE @@ -796,6 +796,21 @@ integer function hdf5_create_sensor(type_id) result(rc) call h5tinsert_f(type_id, 'z', offset, h5kind_to_type(kind(sensor%z), H5_REAL_KIND), stat) if (stat < 0) return + ! Sensor longitude. + offset = h5offsetof(c_loc(sensor), c_loc(sensor%lon)) + call h5tinsert_f(type_id, 'lon', offset, h5kind_to_type(kind(sensor%lon), H5_REAL_KIND), stat) + if (stat < 0) return + + ! Sensor latitude. + offset = h5offsetof(c_loc(sensor), c_loc(sensor%lat)) + call h5tinsert_f(type_id, 'lat', offset, h5kind_to_type(kind(sensor%lat), H5_REAL_KIND), stat) + if (stat < 0) return + + ! Sensor altitude. + offset = h5offsetof(c_loc(sensor), c_loc(sensor%alt)) + call h5tinsert_f(type_id, 'alt', offset, h5kind_to_type(kind(sensor%alt), H5_REAL_KIND), stat) + if (stat < 0) return + rc = E_NONE end function hdf5_create_sensor @@ -859,6 +874,21 @@ integer function hdf5_create_target(type_id) result(rc) call h5tinsert_f(type_id, 'z', offset, h5kind_to_type(kind(target%z), H5_REAL_KIND), stat) if (stat < 0) return + ! Target longitude. + offset = h5offsetof(c_loc(target), c_loc(target%lon)) + call h5tinsert_f(type_id, 'lon', offset, h5kind_to_type(kind(target%lon), H5_REAL_KIND), stat) + if (stat < 0) return + + ! Target latitude. + offset = h5offsetof(c_loc(target), c_loc(target%lat)) + call h5tinsert_f(type_id, 'lat', offset, h5kind_to_type(kind(target%lat), H5_REAL_KIND), stat) + if (stat < 0) return + + ! Target altitude. + offset = h5offsetof(c_loc(target), c_loc(target%alt)) + call h5tinsert_f(type_id, 'alt', offset, h5kind_to_type(kind(target%alt), H5_REAL_KIND), stat) + if (stat < 0) return + rc = E_NONE end function hdf5_create_target diff --git a/src/dm_html.f90 b/src/dm_html.f90 index 84fe564..e980659 100644 --- a/src/dm_html.f90 +++ b/src/dm_html.f90 @@ -1039,11 +1039,11 @@ function dm_html_node(node) result(html) H_TR // H_TH // 'Z' // H_TH_END // & H_TD // dm_ftoa(node%z) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Longitude' // H_TH_END // & - H_TD // dm_ftoa(node%longitude) // H_TD_END // H_TR_END // & + H_TD // dm_ftoa(node%lon) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Latitude' // H_TH_END // & - H_TD // dm_ftoa(node%latitude) // H_TD_END // H_TR_END // & + H_TD // dm_ftoa(node%lat) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Altitude' // H_TH_END // & - H_TD // dm_ftoa(node%altitude) // H_TD_END // H_TR_END // & + H_TD // dm_ftoa(node%alt) // H_TD_END // H_TR_END // & H_TBODY_END // H_TABLE_END end function dm_html_node @@ -1068,9 +1068,6 @@ function dm_html_nodes(nodes, prefix) result(html) H_TH // 'ID' // H_TH_END // & H_TH // 'Name' // H_TH_END // & H_TH // 'Meta' // H_TH_END // & - H_TH // 'Lat.' // H_TH_END // & - H_TH // 'Lng.' // H_TH_END // & - H_TH // 'Z' // H_TH_END // & H_TH // 'X' // H_TH_END // & H_TH // 'Y' // H_TH_END // & H_TH // 'Z' // H_TH_END // & @@ -1093,9 +1090,6 @@ function dm_html_nodes(nodes, prefix) result(html) H_TD // dm_ftoa(nodes(i)%x) // H_TD_END // & H_TD // dm_ftoa(nodes(i)%y) // H_TD_END // & H_TD // dm_ftoa(nodes(i)%z) // H_TD_END // & - H_TD // dm_ftoa(nodes(i)%longitude) // H_TD_END // & - H_TD // dm_ftoa(nodes(i)%latitude) // H_TD_END // & - H_TD // dm_ftoa(nodes(i)%altitude) // H_TD_END // & H_TR_END end do @@ -1470,6 +1464,12 @@ function dm_html_sensor(sensor) result(html) H_TD // dm_ftoa(sensor%y) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Z' // H_TH_END // & H_TD // dm_ftoa(sensor%z) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Longitude' // H_TH_END // & + H_TD // dm_ftoa(sensor%lon) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Latitude' // H_TH_END // & + H_TD // dm_ftoa(sensor%lat) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Altitude' // H_TH_END // & + H_TD // dm_ftoa(sensor%alt) // H_TD_END // H_TR_END // & H_TBODY_END // H_TABLE_END end function dm_html_sensor @@ -1575,6 +1575,12 @@ function dm_html_target(target) result(html) H_TD // dm_ftoa(target%y) // H_TD_END // H_TR_END // & H_TR // H_TH // 'Z' // H_TH_END // & H_TD // dm_ftoa(target%z) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Longitude' // H_TH_END // & + H_TD // dm_ftoa(target%lon) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Latitude' // H_TH_END // & + H_TD // dm_ftoa(target%lat) // H_TD_END // H_TR_END // & + H_TR // H_TH // 'Altitude' // H_TH_END // & + H_TD // dm_ftoa(target%alt) // H_TD_END // H_TR_END // & H_TBODY_END // H_TABLE_END end function dm_html_target diff --git a/src/dm_json.f90 b/src/dm_json.f90 index f7d5873..f62f44f 100644 --- a/src/dm_json.f90 +++ b/src/dm_json.f90 @@ -241,15 +241,15 @@ function json_from_node(node) result(json) type(node_type), intent(inout) :: node !! Node type. character(len=:), allocatable :: json !! Alloctable JSON string. - json = '{"id":"' // trim(node%id) // '",' // & - '"name":"' // trim(node%name) // '",' // & - '"meta":"' // dm_json_escape(node%meta) // '",' // & - '"x":' // dm_ftoa(node%x) // ',' // & - '"y":' // dm_ftoa(node%y) // ',' // & - '"z":' // dm_ftoa(node%z) // ',' // & - '"longitude":' // dm_ftoa(node%longitude) // ',' // & - '"latitude":' // dm_ftoa(node%latitude) // ',' // & - '"altitude":' // dm_ftoa(node%altitude) // '}' + json = '{"id":"' // trim(node%id) // '",' // & + '"name":"' // trim(node%name) // '",' // & + '"meta":"' // dm_json_escape(node%meta) // '",' // & + '"x":' // dm_ftoa(node%x) // ',' // & + '"y":' // dm_ftoa(node%y) // ',' // & + '"z":' // dm_ftoa(node%z) // ',' // & + '"lon":' // dm_ftoa(node%lon) // ',' // & + '"lat":' // dm_ftoa(node%lat) // ',' // & + '"alt":' // dm_ftoa(node%alt) // '}' end function json_from_node function json_from_nodes(nodes) result(json) @@ -401,7 +401,10 @@ function json_from_sensor(sensor) result(json) '"meta":"' // dm_json_escape(sensor%meta) // '",' // & '"x":' // dm_ftoa(sensor%x) // ',' // & '"y":' // dm_ftoa(sensor%y) // ',' // & - '"z":' // dm_ftoa(sensor%z) // '}' + '"z":' // dm_ftoa(sensor%z) // ',' // & + '"lon":' // dm_ftoa(sensor%lon) // ',' // & + '"lat":' // dm_ftoa(sensor%lat) // ',' // & + '"alt":' // dm_ftoa(sensor%alt) // '}' end function json_from_sensor function json_from_sensors(sensors) result(json) @@ -446,7 +449,10 @@ function json_from_target(target) result(json) '"state":' // dm_itoa(target%state) // ',' // & '"x":' // dm_ftoa(target%x) // ',' // & '"y":' // dm_ftoa(target%y) // ',' // & - '"z":' // dm_ftoa(target%z) // '}' + '"z":' // dm_ftoa(target%z) // ',' // & + '"lon":' // dm_ftoa(target%lon) // ',' // & + '"lat":' // dm_ftoa(target%lat) // ',' // & + '"alt":' // dm_ftoa(target%alt) // '}' end function json_from_target function json_from_targets(targets) result(json) diff --git a/src/dm_nml.f90 b/src/dm_nml.f90 index d6f9b7a..8c017c0 100644 --- a/src/dm_nml.f90 +++ b/src/dm_nml.f90 @@ -14,8 +14,8 @@ module dm_nml integer, parameter, public :: NML_LOG_LEN = 960 !! Max. size of `log_type` namelist in bytes. integer, parameter, public :: NML_NODE_LEN = 384 !! Max. size of `node_type` namelist in bytes. integer, parameter, public :: NML_OBSERV_LEN = 46 * 1024 !! Max. size of `observ_type` namelist in bytes. - integer, parameter, public :: NML_SENSOR_LEN = 400 !! Max. size of `sensor_type` namelist in bytes. - integer, parameter, public :: NML_TARGET_LEN = 296 !! Max. size of `target_type` namelist in bytes. + integer, parameter, public :: NML_SENSOR_LEN = 512 !! Max. size of `sensor_type` namelist in bytes. + integer, parameter, public :: NML_TARGET_LEN = 416 !! Max. size of `target_type` namelist in bytes. interface dm_nml_from !! Converts type to static or allocatable namelist string. diff --git a/src/dm_node.f90 b/src/dm_node.f90 index 24361e1..fe03c43 100644 --- a/src/dm_node.f90 +++ b/src/dm_node.f90 @@ -13,15 +13,15 @@ module dm_node type, public :: node_type !! Sensor node type. Uses lon-lat order. - character(len=NODE_ID_LEN) :: id = ' ' !! Node id (`-0-9A-Z_a-z`). - character(len=NODE_NAME_LEN) :: name = ' ' !! Node name. - character(len=NODE_META_LEN) :: meta = ' ' !! Additional description text (optional). - real(kind=r8) :: x = 0.0_r8 !! Local x or easting, usually in metres (optional). - real(kind=r8) :: y = 0.0_r8 !! Local y or northing, usually in metres (optional). - real(kind=r8) :: z = 0.0_r8 !! Local z or altitude, usually in metres (optional). - real(kind=r8) :: longitude = 0.0_r8 !! Longitude in degrees (optional). - real(kind=r8) :: latitude = 0.0_r8 !! Latitude in degrees (optional). - real(kind=r8) :: altitude = 0.0_r8 !! Altitude or elevation in metres (optional). + character(len=NODE_ID_LEN) :: id = ' ' !! Node id (`-0-9A-Z_a-z`). + character(len=NODE_NAME_LEN) :: name = ' ' !! Node name. + character(len=NODE_META_LEN) :: meta = ' ' !! Additional description text (optional). + real(kind=r8) :: x = 0.0_r8 !! Local x or easting, usually in metres (optional). + real(kind=r8) :: y = 0.0_r8 !! Local y or northing, usually in metres (optional). + real(kind=r8) :: z = 0.0_r8 !! Local z or elevation, usually in metres (optional). + real(kind=r8) :: lon = 0.0_r8 !! Longitude in degrees (optional). + real(kind=r8) :: lat = 0.0_r8 !! Latitude in degrees (optional). + real(kind=r8) :: alt = 0.0_r8 !! Altitude or elevation in metres (optional). end type node_type integer, parameter, public :: NODE_SIZE = storage_size(node_type()) / 8 !! Size of `node_type` in bytes. @@ -54,9 +54,9 @@ pure elemental logical function dm_node_equals(node1, node2) result(equals) if (.not. dm_equals(node1%y, node2%y)) return if (.not. dm_equals(node1%z, node2%z)) return - if (.not. dm_equals(node1%longitude, node2%longitude)) return - if (.not. dm_equals(node1%latitude, node2%latitude)) return - if (.not. dm_equals(node1%altitude, node2%altitude)) return + if (.not. dm_equals(node1%lon, node2%lon)) return + if (.not. dm_equals(node1%lat, node2%lat)) return + if (.not. dm_equals(node1%alt, node2%alt)) return equals= .true. end function dm_node_equals @@ -81,14 +81,14 @@ subroutine dm_node_out(node, unit) unit_ = stdout if (present(unit)) unit_ = unit - write (unit_, '("node.id: ", a)') trim(node%id) - write (unit_, '("node.name: ", a)') trim(node%name) - write (unit_, '("node.meta: ", a)') trim(node%meta) - write (unit_, '("node.x: ", 1pg0.12)') node%x - write (unit_, '("node.y: ", 1pg0.12)') node%y - write (unit_, '("node.z: ", 1pg0.12)') node%z - write (unit_, '("node.longitude: ", 1pg0.12)') node%longitude - write (unit_, '("node.latitude: ", 1pg0.12)') node%latitude - write (unit_, '("node.altitude: ", 1pg0.12)') node%altitude + write (unit_, '("node.id: ", a)') trim(node%id) + write (unit_, '("node.name: ", a)') trim(node%name) + write (unit_, '("node.meta: ", a)') trim(node%meta) + write (unit_, '("node.x: ", 1pg0.12)') node%x + write (unit_, '("node.y: ", 1pg0.12)') node%y + write (unit_, '("node.z: ", 1pg0.12)') node%z + write (unit_, '("node.lon: ", 1pg0.12)') node%lon + write (unit_, '("node.lat: ", 1pg0.12)') node%lat + write (unit_, '("node.alt: ", 1pg0.12)') node%alt end subroutine dm_node_out end module dm_node diff --git a/src/dm_sensor.f90 b/src/dm_sensor.f90 index 9adb773..787b010 100644 --- a/src/dm_sensor.f90 +++ b/src/dm_sensor.f90 @@ -45,7 +45,10 @@ module dm_sensor character(len=SENSOR_META_LEN) :: meta = ' ' !! Meta information (optional). real(kind=r8) :: x = 0.0_r8 !! Sensor x or easting (optional). real(kind=r8) :: y = 0.0_r8 !! Sensor y or northing (optional). - real(kind=r8) :: z = 0.0_r8 !! Sensor z or altitude (optional). + real(kind=r8) :: z = 0.0_r8 !! Sensor z or alt (optional). + real(kind=r8) :: lon = 0.0_r8 !! Longitude in degrees (optional). + real(kind=r8) :: lat = 0.0_r8 !! Latitude in degrees (optional). + real(kind=r8) :: alt = 0.0_r8 !! Altitude or elevation in metres (optional). end type sensor_type integer, parameter, public :: SENSOR_SIZE = storage_size(sensor_type()) / 8 !! Size of `sensor_type` in bytes. @@ -85,6 +88,10 @@ pure elemental logical function dm_sensor_equals(sensor1, sensor2) result(equals if (.not. dm_equals(sensor1%y, sensor2%y)) return if (.not. dm_equals(sensor1%z, sensor2%z)) return + if (.not. dm_equals(sensor1%lon, sensor2%lon)) return + if (.not. dm_equals(sensor1%lat, sensor2%lat)) return + if (.not. dm_equals(sensor1%alt, sensor2%alt)) return + equals = .true. end function dm_sensor_equals @@ -168,11 +175,14 @@ subroutine dm_sensor_out(sensor, unit) write (unit_, '("invalid")') end if - write (unit_, '("sensor.name: ", a)') trim(sensor%name) - write (unit_, '("sensor.sn: ", a)') trim(sensor%sn) - write (unit_, '("sensor.meta: ", a)') trim(sensor%meta) - write (unit_, '("sensor.x: ", 1pg0.12)') sensor%x - write (unit_, '("sensor.y: ", 1pg0.12)') sensor%y - write (unit_, '("sensor.z: ", 1pg0.12)') sensor%z + write (unit_, '("sensor.name: ", a)') trim(sensor%name) + write (unit_, '("sensor.sn: ", a)') trim(sensor%sn) + write (unit_, '("sensor.meta: ", a)') trim(sensor%meta) + write (unit_, '("sensor.x: ", 1pg0.12)') sensor%x + write (unit_, '("sensor.y: ", 1pg0.12)') sensor%y + write (unit_, '("sensor.z: ", 1pg0.12)') sensor%z + write (unit_, '("sensor.lon: ", 1pg0.12)') sensor%lon + write (unit_, '("sensor.lat: ", 1pg0.12)') sensor%lat + write (unit_, '("sensor.alt: ", 1pg0.12)') sensor%alt end subroutine dm_sensor_out end module dm_sensor diff --git a/src/dm_sql.f90 b/src/dm_sql.f90 index d06aade..9740805 100644 --- a/src/dm_sql.f90 +++ b/src/dm_sql.f90 @@ -66,82 +66,82 @@ module dm_sql ! Logs schema character(len=*), parameter, public :: SQL_CREATE_LOGS = & 'CREATE TABLE IF NOT EXISTS logs(' // NL // & - 'log_id INTEGER PRIMARY KEY,' // NL // & - 'id TEXT NOT NULL UNIQUE,' // NL // & - 'level INTEGER NOT NULL DEFAULT 0,' // NL // & - 'error INTEGER NOT NULL DEFAULT 0,' // NL // & - 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & - 'node_id TEXT,' // NL // & - 'sensor_id TEXT,' // NL // & - 'target_id TEXT,' // NL // & - 'observ_id TEXT,' // NL // & - 'source TEXT,' // NL // & - 'message TEXT) STRICT' + 'log_id INTEGER PRIMARY KEY,' // NL // & + 'id TEXT NOT NULL UNIQUE,' // NL // & + 'level INTEGER NOT NULL DEFAULT 0,' // NL // & + 'error INTEGER NOT NULL DEFAULT 0,' // NL // & + 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & + 'node_id TEXT,' // NL // & + 'sensor_id TEXT,' // NL // & + 'target_id TEXT,' // NL // & + 'observ_id TEXT,' // NL // & + 'source TEXT,' // NL // & + 'message TEXT) STRICT' ! Sensor nodes schema. character(len=*), parameter, public :: SQL_CREATE_NODES = & 'CREATE TABLE IF NOT EXISTS nodes(' // NL // & - 'node_id INTEGER PRIMARY KEY,' // NL // & - 'id TEXT NOT NULL UNIQUE,' // NL // & - 'name TEXT NOT NULL,' // NL // & - 'meta TEXT,' // NL // & - 'x REAL NOT NULL DEFAULT 0.0,' // NL // & - 'y REAL NOT NULL DEFAULT 0.0,' // NL // & - 'z REAL NOT NULL DEFAULT 0.0,' // NL // & - 'longitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'latitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'altitude REAL NOT NULL DEFAULT 0.0) STRICT' + 'node_id INTEGER PRIMARY KEY,' // NL // & + 'id TEXT NOT NULL UNIQUE,' // NL // & + 'name TEXT NOT NULL,' // NL // & + 'meta TEXT,' // NL // & + 'x REAL NOT NULL DEFAULT 0.0,' // NL // & + 'y REAL NOT NULL DEFAULT 0.0,' // NL // & + 'z REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lon REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lat REAL NOT NULL DEFAULT 0.0,' // NL // & + 'alt REAL NOT NULL DEFAULT 0.0) STRICT' ! Sensors schema. character(len=*), parameter, public :: SQL_CREATE_SENSORS = & 'CREATE TABLE IF NOT EXISTS sensors(' // NL // & - 'sensor_id INTEGER PRIMARY KEY,' // NL // & - 'node_id INTEGER NOT NULL,' // NL // & - 'id TEXT NOT NULL UNIQUE,' // NL // & - 'type INTEGER NOT NULL DEFAULT 0,' // NL // & - 'name TEXT NOT NULL,' // NL // & - 'sn TEXT,' // NL // & - 'meta TEXT,' // NL // & - 'x REAL NOT NULL DEFAULT 0.0,' // NL // & - 'y REAL NOT NULL DEFAULT 0.0,' // NL // & - 'z REAL NOT NULL DEFAULT 0.0,' // NL // & - 'longitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'latitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'altitude REAL NOT NULL DEFAULT 0.0,' // NL // & + 'sensor_id INTEGER PRIMARY KEY,' // NL // & + 'node_id INTEGER NOT NULL,' // NL // & + 'id TEXT NOT NULL UNIQUE,' // NL // & + 'type INTEGER NOT NULL DEFAULT 0,' // NL // & + 'name TEXT NOT NULL,' // NL // & + 'sn TEXT,' // NL // & + 'meta TEXT,' // NL // & + 'x REAL NOT NULL DEFAULT 0.0,' // NL // & + 'y REAL NOT NULL DEFAULT 0.0,' // NL // & + 'z REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lon REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lat REAL NOT NULL DEFAULT 0.0,' // NL // & + 'alt REAL NOT NULL DEFAULT 0.0,' // NL // & 'FOREIGN KEY (node_id) REFERENCES nodes(node_id)) STRICT' ! Targets schema. character(len=*), parameter, public :: SQL_CREATE_TARGETS = & 'CREATE TABLE IF NOT EXISTS targets(' // NL // & - 'target_id INTEGER PRIMARY KEY,' // NL // & - 'id TEXT NOT NULL UNIQUE,' // NL // & - 'name TEXT,' // NL // & - 'meta TEXT,' // NL // & - 'state INTEGER NOT NULL DEFAULT 0,' // NL // & - 'x REAL NOT NULL DEFAULT 0.0,' // NL // & - 'y REAL NOT NULL DEFAULT 0.0,' // NL // & - 'z REAL NOT NULL DEFAULT 0.0,' // NL // & - 'longitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'latitude REAL NOT NULL DEFAULT 0.0,' // NL // & - 'altitude REAL NOT NULL DEFAULT 0.0) STRICT' + 'target_id INTEGER PRIMARY KEY,' // NL // & + 'id TEXT NOT NULL UNIQUE,' // NL // & + 'name TEXT,' // NL // & + 'meta TEXT,' // NL // & + 'state INTEGER NOT NULL DEFAULT 0,' // NL // & + 'x REAL NOT NULL DEFAULT 0.0,' // NL // & + 'y REAL NOT NULL DEFAULT 0.0,' // NL // & + 'z REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lon REAL NOT NULL DEFAULT 0.0,' // NL // & + 'lat REAL NOT NULL DEFAULT 0.0,' // NL // & + 'alt REAL NOT NULL DEFAULT 0.0) STRICT' ! Observations schema. character(len=*), parameter, public :: SQL_CREATE_OBSERVS = & 'CREATE TABLE IF NOT EXISTS observs(' // NL // & - 'observ_id INTEGER PRIMARY KEY,' // NL // & - 'node_id INTEGER NOT NULL,' // NL // & - 'sensor_id INTEGER NOT NULL,' // NL // & - 'target_id INTEGER NOT NULL,' // NL // & - 'id TEXT NOT NULL UNIQUE,' // NL // & - 'name TEXT NOT NULL,' // NL // & - 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & - 'source TEXT,' // NL // & - 'device TEXT,' // NL // & - 'priority INTEGER NOT NULL DEFAULT 0,' // NL // & - 'error INTEGER NOT NULL DEFAULT 0,' // NL // & - 'next INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nreceivers INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nrequests INTEGER NOT NULL DEFAULT 0,' // NL // & + 'observ_id INTEGER PRIMARY KEY,' // NL // & + 'node_id INTEGER NOT NULL,' // NL // & + 'sensor_id INTEGER NOT NULL,' // NL // & + 'target_id INTEGER NOT NULL,' // NL // & + 'id TEXT NOT NULL UNIQUE,' // NL // & + 'name TEXT NOT NULL,' // NL // & + 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & + 'source TEXT,' // NL // & + 'device TEXT,' // NL // & + 'priority INTEGER NOT NULL DEFAULT 0,' // NL // & + 'error INTEGER NOT NULL DEFAULT 0,' // NL // & + 'next INTEGER NOT NULL DEFAULT 0,' // NL // & + 'nreceivers INTEGER NOT NULL DEFAULT 0,' // NL // & + 'nrequests INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (node_id) REFERENCES nodes(node_id),' // NL // & 'FOREIGN KEY (sensor_id) REFERENCES sensors(sensor_id),' // NL // & 'FOREIGN KEY (target_id) REFERENCES targets(target_id)) STRICT' @@ -159,22 +159,22 @@ module dm_sql ! Requests schema. character(len=*), parameter, public :: SQL_CREATE_REQUESTS = & 'CREATE TABLE IF NOT EXISTS requests(' // NL // & - 'request_id INTEGER PRIMARY KEY,' // NL // & - 'observ_id INTEGER NOT NULL,' // NL // & - 'idx INTEGER NOT NULL,' // NL // & - 'name TEXT NOT NULL,' // NL // & - 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & - 'request TEXT,' // NL // & - 'response TEXT,' // NL // & - 'delimiter TEXT,' // NL // & - 'pattern TEXT,' // NL // & - 'delay INTEGER NOT NULL DEFAULT 0,' // NL // & - 'error INTEGER NOT NULL DEFAULT 0,' // NL // & - 'mode INTEGER NOT NULL DEFAULT 0,' // NL // & - 'retries INTEGER NOT NULL DEFAULT 0,' // NL // & - 'state INTEGER NOT NULL DEFAULT 0,' // NL // & - 'timeout INTEGER NOT NULL DEFAULT 0,' // NL // & - 'nresponses INTEGER NOT NULL DEFAULT 0,' // NL // & + 'request_id INTEGER PRIMARY KEY,' // NL // & + 'observ_id INTEGER NOT NULL,' // NL // & + 'idx INTEGER NOT NULL,' // NL // & + 'name TEXT NOT NULL,' // NL // & + 'timestamp TEXT NOT NULL DEFAULT (strftime(''%FT%R:%f000+00:00'')),' // NL // & + 'request TEXT,' // NL // & + 'response TEXT,' // NL // & + 'delimiter TEXT,' // NL // & + 'pattern TEXT,' // NL // & + 'delay INTEGER NOT NULL DEFAULT 0,' // NL // & + 'error INTEGER NOT NULL DEFAULT 0,' // NL // & + 'mode INTEGER NOT NULL DEFAULT 0,' // NL // & + 'retries INTEGER NOT NULL DEFAULT 0,' // NL // & + 'state INTEGER NOT NULL DEFAULT 0,' // NL // & + 'timeout INTEGER NOT NULL DEFAULT 0,' // NL // & + 'nresponses INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (observ_id) REFERENCES observs(observ_id),' // NL // & 'UNIQUE (observ_id, idx) ON CONFLICT REPLACE) STRICT' @@ -198,11 +198,11 @@ module dm_sql ! Synchronised logs schema. character(len=*), parameter, public :: SQL_CREATE_SYNC_LOGS = & 'CREATE TABLE IF NOT EXISTS sync_logs(' // NL // & - 'sync_log_id INTEGER PRIMARY KEY,' // NL // & - '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 // & - 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & + 'sync_log_id INTEGER PRIMARY KEY,' // NL // & + '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 // & + 'attempts INTEGER NOT NULL DEFAULT 0,' // NL // & 'FOREIGN KEY (log_id) REFERENCES logs(log_id)) STRICT' ! Synchronised nodes schema. @@ -388,22 +388,26 @@ module dm_sql 'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' ! Query to insert node. - ! Arguments: nodes.id, nodes.name, nodes.meta + ! Arguments: nodes.id, nodes.name, nodes.meta, nodes.x, nodes.y, nodes.z, + ! nodes.lon, nodes.lat, nodes.alt character(len=*), parameter, public :: SQL_INSERT_NODE = & - 'INSERT OR FAIL INTO nodes(id, name, meta, x, y, z, longitude, latitude, altitude) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)' + 'INSERT OR FAIL INTO nodes(id, name, meta, x, y, z, lon, lat, alt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)' ! Query to insert sensor. ! Arguments: sensors.id, nodes.id, sensors.type, sensors.id, sensors.name, - ! sensors.sn, sensors.meta + ! sensors.sn, sensors.meta, sensors.x, sensors.y, sensors.z, + ! sensors.lon, sensors.lat, sensors.alt character(len=*), parameter, public :: SQL_INSERT_SENSOR = & - 'INSERT OR FAIL INTO sensors(id, node_id, type, name, sn, meta, x, y, z) VALUES (' // & - '?, (SELECT node_id FROM nodes WHERE id = ?), ?, ?, ?, ?, ?, ?, ?)' + 'INSERT OR FAIL INTO sensors(id, node_id, type, name, sn, meta, x, y, z, lon, lat, alt) VALUES (' // & + '?, (SELECT node_id FROM nodes WHERE id = ?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' ! Query to insert target. ! Arguments: targets.id, targets.name, targets.meta, targets.state, - ! targets.x, targets.y, targets.z + ! targets.x, targets.y, targets.z, targets.lon, targets.lat, + ! targets.alt character(len=*), parameter, public :: SQL_INSERT_TARGET = & - 'INSERT OR FAIL INTO targets(id, name, meta, state, x, y, z) VALUES (?, ?, ?, ?, ?, ?, ?)' + 'INSERT OR FAIL INTO targets(id, name, meta, state, x, y, z, lon, lat, alt) VALUES (' // & + '?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' ! Query to insert observation. ! Arguments: nodes.id, sensors.id, targets.id, observs.id, observs.name, @@ -450,22 +454,25 @@ module dm_sql ! UPDATE QUERIES. ! ****************************************************************** ! Query to update node. - ! Arguments: nodes.name, nodes.meta, nodes.id + ! Arguments: nodes.name, nodes.meta, nodes.x, nodes.y, nodes.z + ! nodes.lon, nodes.lat, nodes.alt, nodes.id character(len=*), parameter, public :: SQL_UPDATE_NODE = & - 'UPDATE OR FAIL nodes SET name = ?, meta = ?, x = ?, y = ?, z = ?, longitude = ?, latitude = ?, altitude = ? WHERE id = ?' + 'UPDATE OR FAIL nodes SET name = ?, meta = ?, x = ?, y = ?, z = ?, lon = ?, lat = ?, alt = ? WHERE id = ?' ! Query to update sensor. ! Arguments: nodes.id, sensors.type, sensors.id, sensors.name, sensors.sn, - ! sensors.meta, sensors.id + ! sensors.meta, sensors.x, sensors.y, sensors.z, sensors.lon, + ! sensors.lat, sensors.alt, sensors.id character(len=*), parameter, public :: SQL_UPDATE_SENSOR = & 'UPDATE OR FAIL sensors SET node_id = (SELECT node_id FROM nodes WHERE id = ?), ' // & - 'type = ?, name = ?, sn = ?, meta = ?, x = ?, y = ?, z = ? WHERE id = ?' + 'type = ?, name = ?, sn = ?, meta = ?, x = ?, y = ?, z = ?, lon = ?, lat = ?, alt = ? WHERE id = ?' ! Query to update target. ! Arguments: targets.name, targets.meta, targets.state, targets.x, targets.y, - ! targets.z, targets.id + ! targets.z, targets.lon, targets.lat, targets.alt, targets.id character(len=*), parameter, public :: SQL_UPDATE_TARGET = & - 'UPDATE OR FAIL targets SET name = ?, meta = ?, state = ?, x = ?, y = ?, z = ? WHERE id = ?' + 'UPDATE OR FAIL targets SET name = ?, meta = ?, state = ?, x = ?, y = ?, z = ?, ' // & + 'lon = ?, lat = ?, alt = ? WHERE id = ?' ! ****************************************************************** ! SELECT EXISTS QUERIES. @@ -598,9 +605,9 @@ module dm_sql 'nodes.x, ' // & 'nodes.y, ' // & 'nodes.z, ' // & - 'nodes.longitude, ' // & - 'nodes.latitude, ' // & - 'nodes.altitude ' // & + 'nodes.lon, ' // & + 'nodes.lat, ' // & + 'nodes.alt ' // & 'FROM nodes WHERE nodes.id = ?' ! Query to select all nodes. @@ -612,9 +619,9 @@ module dm_sql 'nodes.x, ' // & 'nodes.y, ' // & 'nodes.z, ' // & - 'nodes.longitude, ' // & - 'nodes.latitude, ' // & - 'nodes.altitude ' // & + 'nodes.lon, ' // & + 'nodes.lat, ' // & + 'nodes.alt ' // & 'FROM nodes ORDER BY nodes.id ASC' ! Query to select number of time series by time range. @@ -877,7 +884,10 @@ module dm_sql 'sensors.meta, ' // & 'sensors.x, ' // & 'sensors.y, ' // & - 'sensors.z ' // & + 'sensors.z, ' // & + 'sensors.lon, ' // & + 'sensors.lat, ' // & + 'sensors.alt ' // & 'FROM sensors ' // & 'INNER JOIN nodes ON nodes.node_id = sensors.node_id ' // & 'WHERE sensors.id = ?' @@ -893,7 +903,10 @@ module dm_sql 'sensors.meta, ' // & 'sensors.x, ' // & 'sensors.y, ' // & - 'sensors.z ' // & + 'sensors.z, ' // & + 'sensors.lon, ' // & + 'sensors.lat, ' // & + 'sensors.alt ' // & 'FROM sensors ' // & 'INNER JOIN nodes ON nodes.node_id = sensors.node_id ' // & 'ORDER BY sensors.id ASC' @@ -910,7 +923,10 @@ module dm_sql 'sensors.meta, ' // & 'sensors.x, ' // & 'sensors.y, ' // & - 'sensors.z ' // & + 'sensors.z, ' // & + 'sensors.lon, ' // & + 'sensors.lat, ' // & + 'sensors.alt ' // & 'FROM sensors ' // & 'INNER JOIN nodes ON nodes.node_id = sensors.node_id ' // & 'WHERE nodes.id = ?' @@ -925,7 +941,10 @@ module dm_sql 'targets.state, ' // & 'targets.x, ' // & 'targets.y, ' // & - 'targets.z ' // & + 'targets.z, ' // & + 'targets.lon, ' // & + 'targets.lat, ' // & + 'targets.alt ' // & 'FROM targets WHERE targets.id = ?' ! Query to select all targets. @@ -937,7 +956,10 @@ module dm_sql 'targets.state, ' // & 'targets.x, ' // & 'targets.y, ' // & - 'targets.z ' // & + 'targets.z, ' // & + 'targets.lon, ' // & + 'targets.lat, ' // & + 'targets.alt ' // & 'FROM targets ORDER BY targets.id ASC' ! ****************************************************************** @@ -1107,20 +1129,22 @@ module dm_sql character(len=*), parameter, public :: SQL_SELECT_JSON_NODES = & 'SELECT ' // & 'json_object(''id'', id, ''name'', name, ''meta'', meta, ''x'', x, ''y'', y, ''z'', z, ' // & - '''longitude'', longitude, ''latitude'', latitude, ''altitude'', altitude) ' // & + '''lon'', lon, ''lat'', lat, ''alt'', alt) ' // & 'FROM nodes' ! Query to select all sensors in JSON format. character(len=*), parameter, public :: SQL_SELECT_JSON_SENSORS = & 'SELECT ' // & 'json_object(''id'', sensors.id, ''node_id'', nodes.id, ''type'', sensors.type, ''name'', ''sensors.name, ' // & - '''sn'', sensors.sn, ''meta'', sensors.meta, ''x'', sensors.x, ''y'', sensors.y, ''z'', sensors.z) ' // & + '''sn'', sensors.sn, ''meta'', sensors.meta, ''x'', sensors.x, ''y'', sensors.y, ''z'', sensors.z, ' // & + '''lon'', sensors.lon, ''lat'', sensors.lat, ''alt'', sensors.alt) ' // & 'FROM sensors ' // & 'INNER JOIN nodes ON nodes.node_id = sensors.node_id' ! Query to select all targets in JSON format. character(len=*), parameter, public :: SQL_SELECT_JSON_TARGETS = & 'SELECT ' // & - 'json_object(''id'', id, ''name'', name, ''meta'', meta, ''state'', state, ''x'', x, ''y'', y, ''z'', z) ' // & + 'json_object(''id'', id, ''name'', name, ''meta'', meta, ''state'', state, ''x'', x, ''y'', y, ''z'', z, ' // & + '''lon'', lon, ''lat'', lat, ''alt'', alt) ' // & 'FROM targets ORDER BY id ASC' end module dm_sql diff --git a/src/dm_target.f90 b/src/dm_target.f90 index b0e5d86..9e19b28 100644 --- a/src/dm_target.f90 +++ b/src/dm_target.f90 @@ -37,6 +37,9 @@ module dm_target real(kind=r8) :: x = 0.0_r8 !! Target x or easting (optional). real(kind=r8) :: y = 0.0_r8 !! Target y or northing (optional). real(kind=r8) :: z = 0.0_r8 !! Target z or altitude (optional). + real(kind=r8) :: lon = 0.0_r8 !! Longitude in degrees (optional). + real(kind=r8) :: lat = 0.0_r8 !! Latitude in degrees (optional). + real(kind=r8) :: alt = 0.0_r8 !! Altitude or elevation in metres (optional). end type target_type integer, parameter, public :: TARGET_SIZE = storage_size(target_type()) / 8 !! Size of `target_type` in bytes. @@ -60,13 +63,20 @@ pure elemental logical function dm_target_equals(target1, target2) result(equals type(target_type), intent(in) :: target2 !! The second target. equals = .false. - if (target1%id /= target2%id) return - if (target1%name /= target2%name) return - if (target1%meta /= target2%meta) return - if (target1%state /= target2%state) return + + if (target1%id /= target2%id) return + if (target1%name /= target2%name) return + if (target1%meta /= target2%meta) return + if (target1%state /= target2%state) return + if (.not. dm_equals(target1%x, target2%x)) return if (.not. dm_equals(target1%y, target2%y)) return if (.not. dm_equals(target1%z, target2%z)) return + + if (.not. dm_equals(target1%lon, target2%lon)) return + if (.not. dm_equals(target1%lat, target2%lat)) return + if (.not. dm_equals(target1%alt, target2%alt)) return + equals= .true. end function dm_target_equals @@ -113,12 +123,15 @@ subroutine dm_target_out(target, unit) unit_ = stdout if (present(unit)) unit_ = unit - write (unit_, '("target.id: ", a)') trim(target%id) - write (unit_, '("target.name: ", a)') trim(target%name) - write (unit_, '("target.meta: ", a)') trim(target%meta) - write (unit_, '("target.state: ", i0)') target%state - write (unit_, '("target.x: ", 1pg0.12)') target%x - write (unit_, '("target.y: ", 1pg0.12)') target%y - write (unit_, '("target.z: ", 1pg0.12)') target%z + write (unit_, '("target.id: ", a)') trim(target%id) + write (unit_, '("target.name: ", a)') trim(target%name) + write (unit_, '("target.meta: ", a)') trim(target%meta) + write (unit_, '("target.state: ", i0)') target%state + write (unit_, '("target.x: ", 1pg0.12)') target%x + write (unit_, '("target.y: ", 1pg0.12)') target%y + write (unit_, '("target.z: ", 1pg0.12)') target%z + write (unit_, '("target.lon: ", 1pg0.12)') target%lon + write (unit_, '("target.lat: ", 1pg0.12)') target%lat + write (unit_, '("target.alt: ", 1pg0.12)') target%alt end subroutine dm_target_out end module dm_target diff --git a/src/dm_test.f90 b/src/dm_test.f90 index 1271fa3..7498a9d 100644 --- a/src/dm_test.f90 +++ b/src/dm_test.f90 @@ -136,15 +136,15 @@ pure elemental subroutine dm_test_dummy_node(node, id, name) character(len=*), intent(in), optional :: id !! Node id. character(len=*), intent(in), optional :: name !! Node name. - node%id = 'dummy-node' - node%name = 'Dummy Node' - node%meta = 'dummy description' - node%x = 100.0_r8 - node%y = 200.0_r8 - node%z = 10.0_r8 - node%longitude = 10.4541194_r8 - node%latitude = 51.1642292_r8 - node%altitude = 100.0_r8 + node%id = 'dummy-node' + node%name = 'Dummy Node' + node%meta = 'dummy description' + node%x = 100.0_r8 + node%y = 200.0_r8 + node%z = 10.0_r8 + node%lon = 10.4541194_r8 + node%lat = 51.1642292_r8 + node%alt = 100.0_r8 if (present(id)) node%id = id if (present(name)) node%name = name diff --git a/src/dm_util.f90 b/src/dm_util.f90 index ff8b300..67eecac 100644 --- a/src/dm_util.f90 +++ b/src/dm_util.f90 @@ -7,7 +7,6 @@ module dm_util implicit none (type, external) private - character(len=*), parameter :: FMT_INTEGER = '(i0)' character(len=*), parameter :: FMT_REAL = '(1pg0.12)' diff --git a/test/dmtestcsv.f90 b/test/dmtestcsv.f90 index 3811c21..7e9f230 100644 --- a/test/dmtestcsv.f90 +++ b/test/dmtestcsv.f90 @@ -224,11 +224,11 @@ logical function test05() result(stat) integer, parameter :: LEN_BEAT = 66 !! Beats header length. integer, parameter :: LEN_DP = 4 !! Data points header length. integer, parameter :: LEN_LOG = 71 !! Logs header length. - integer, parameter :: LEN_NODE = 47 !! Nodes header length. + integer, parameter :: LEN_NODE = 31 !! Nodes header length. integer, parameter :: LEN_OBSERV = 22100 !! Observations header length. integer, parameter :: LEN_VIEW = 180 !! Observation views header length. - integer, parameter :: LEN_SENSOR = 35 !! Sensors header length. - integer, parameter :: LEN_TARGET = 25 !! Targets header length. + integer, parameter :: LEN_SENSOR = 47 !! Sensors header length. + integer, parameter :: LEN_TARGET = 37 !! Targets header length. integer :: n @@ -239,6 +239,7 @@ logical function test05() result(stat) print *, '-- beat' n = len(dm_csv_header_beat()) if (n /= LEN_BEAT) then + print *, dm_csv_header_beat() print '(" Error: expected ", i0, ", got ", i0)', LEN_BEAT, n return end if @@ -246,6 +247,7 @@ logical function test05() result(stat) print *, '-- data point' n = len(dm_csv_header_data_point()) if (n /= LEN_DP) then + print *, dm_csv_header_data_point() print '(" Error: expected ", i0, ", got ", i0)', LEN_DP, n return end if @@ -253,6 +255,7 @@ logical function test05() result(stat) print *, '-- log' n = len(dm_csv_header_log()) if (n /= LEN_LOG) then + print *, dm_csv_header_log() print '(" Error: expected ", i0, ", got ", i0)', LEN_LOG, n return end if @@ -260,6 +263,7 @@ logical function test05() result(stat) print *, '-- node' n = len(dm_csv_header_node()) if (n /= LEN_NODE) then + print *, dm_csv_header_node() print '(" Error: expected ", i0, ", got ", i0)', LEN_NODE, n return end if @@ -267,6 +271,7 @@ logical function test05() result(stat) print *, '-- observ' n = len(dm_csv_header_observ()) if (n /= LEN_OBSERV) then + print *, dm_csv_header_observ() print '(" Error: expected ", i0, ", got ", i0)', LEN_OBSERV, n return end if @@ -274,6 +279,7 @@ logical function test05() result(stat) print *, '-- observ_view' n = len(dm_csv_header_observ_view()) if (n /= LEN_VIEW) then + print *, dm_csv_header_observ_view() print '(" Error: expected ", i0, ", got ", i0)', LEN_VIEW, n return end if @@ -281,6 +287,7 @@ logical function test05() result(stat) print *, '-- sensor' n = len(dm_csv_header_sensor()) if (n /= LEN_SENSOR) then + print *, dm_csv_header_sensor() print '(" Error: expected ", i0, ", got ", i0)', LEN_SENSOR, n return end if @@ -288,6 +295,7 @@ logical function test05() result(stat) print *, '-- target' n = len(dm_csv_header_target()) if (n /= LEN_TARGET) then + print *, dm_csv_header_target() print '(" Error: expected ", i0, ", got ", i0)', LEN_TARGET, n return end if diff --git a/test/dmtestjson.f90 b/test/dmtestjson.f90 index f48982e..4ee0a9e 100644 --- a/test/dmtestjson.f90 +++ b/test/dmtestjson.f90 @@ -279,22 +279,22 @@ logical function test08() result(stat) character(len=*), parameter :: JSON = & '{"id":"dummy-node","name":"Dummy Node","meta":"",' // & '"x":1000.00000000,"y":2000.00000000,"z":10.0000000000,' // & - '"longitude":1.00000000000,"latitude":2.00000000000,"altitude":3.00000000000}' + '"lon":1.00000000000,"lat":2.00000000000,"alt":3.00000000000}' character(len=:), allocatable :: buf type(node_type) :: node stat = TEST_FAILED - node = node_type(id = 'dummy-node', & - name = 'Dummy Node', & - meta = '', & - x = 1000.0_r8, & - y = 2000.0_r8, & - z = 10.0_r8, & - longitude = 1.0_r8, & - latitude = 2.0_r8, & - altitude = 3.0_r8) + node = node_type(id = 'dummy-node', & + name = 'Dummy Node', & + meta = '', & + x = 1000.0_r8, & + y = 2000.0_r8, & + z = 10.0_r8, & + lon = 1.0_r8, & + lat = 2.0_r8, & + alt = 3.0_r8) buf = dm_json_from(node) @@ -318,7 +318,8 @@ end function test08 logical function test09() result(stat) character(len=*), parameter :: JSON = & '{"id":"dummy-sensor","node_id":"dummy-node","type":0,"name":"Dummy Sensor",' // & - '"sn":"12345","meta":"","x":1000.00000000,"y":2000.00000000,"z":10.0000000000}' + '"sn":"12345","meta":"","x":1000.00000000,"y":2000.00000000,"z":10.0000000000,' // & + '"lon":1.00000000000,"lat":2.00000000000,"alt":3.00000000000}' character(len=:), allocatable :: buf type(sensor_type) :: sensor @@ -333,7 +334,10 @@ logical function test09() result(stat) meta = '', & x = 1000.0_r8, & y = 2000.0_r8, & - z = 10.0_r8) + z = 10.0_r8, & + lon = 1.0_r8, & + lat = 2.0_r8, & + alt = 3.0_r8) buf = dm_json_from(sensor) @@ -357,7 +361,8 @@ end function test09 logical function test10() result(stat) character(len=*), parameter :: JSON = & '{"id":"dummy-target","name":"Dummy Target","meta":"",' // & - '"state":1,"x":1000.00000000,"y":2000.00000000,"z":10.0000000000}' + '"state":1,"x":1000.00000000,"y":2000.00000000,"z":10.0000000000,' // & + '"lon":1.00000000000,"lat":2.00000000000,"alt":3.00000000000}' character(len=:), allocatable :: buf type(target_type) :: target @@ -370,7 +375,10 @@ logical function test10() result(stat) state = TARGET_STATE_REMOVED, & x = 1000.0_r8, & y = 2000.0_r8, & - z = 10.0_r8) + z = 10.0_r8, & + lon = 1.0_r8, & + lat = 2.0_r8, & + alt = 3.0_r8) buf = dm_json_from(target)