-
-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support OpenStreetMap as data source #97
Comments
In #96 I am currently adding OpenChargeMap as a data source (see also #81) and also restructuring the app's code to allow for interchangeable data sources as much as possible. So that might also make it possible to add OpenStreetMap. But I have a few concerns (mainly as I'm not familiar with that data source):
|
I don't yet have good data, but here's a preview of the data in Switzerland: https://umap.osm.ch/de/map/electromobility-charging-stations-in-switzerland-b_941#8/46.770/8.086 I'd estimate that there are still a lot of charging stations missing, but that may be because there's no good app for searching/displaying this data so far.
Yes, check out https://wiki.openstreetmap.org/wiki/DE:Tag:amenity%3Dcharging_station for the tagging schema. It's quite powerful.
If the license is compatible, imports into OSM would be possible as well. I myself will definitely start to invest some time into improving the data, and I know a few people that are quite active in the OSM community that might help.
I think the data could be queried through Overpass: https://wiki.openstreetmap.org/wiki/Overpass_API However, I'm not sure how fast this will be in practice. The ideal solution would be to fetch the OSM database, extract the data and then use a webservice endpoint that serves this data from a PostGIS database. I could certainly help with setting up such a setup, but it's definitely an investment (time and server resources), because the full dataset is quite large. (I wrote the POI server for Threema, so I have some experience with these things.) The advantage is that you have full control over the type of information that is extracted, and can optimize the querying using appropriate database indexes. Maybe @sfkeller or @packi have some ideas as well?
Regarding the Overpass API I'm not sure, I think you can use it as long as you don't download huge datasets. Overpass is also not a central service, so there are multiple servers / service providers that may have different terms of use. Again, maybe @sfkeller or @packi have some experience with that. |
I can confirm what @dbrgn wrote above. The Overpass API (over http with json/geojson response) is a well known "entry point" to get data out of OSM (see User's Manual https://dev.overpass-api.de/overpass-doc/en/ ). It's restricted to some MB of data though. There's a nice diagram about choosing a tool to extract OSM data - which is a bit biased towards their 2ohsome framework", but still useful: http://k1z.blog.uni-heidelberg.de/2020/09/10/the-future-of-working-with-osm-data/ . And since OSM is an established crowdsourcing platform with "critial" mass of users, one can assume that it's capable to complete charging stations within few months. See e.g. this action which already got a proposal to map charging stations: https://wiki.openstreetmap.org/wiki/DE:Project_of_the_month_Switzerland . |
Okay, so it looks like the current data in Switzerland does have a large number of stations, but many with a low amount of metadata (e.g. no information about which plugs are available and with what power, which is quite essential information). But I agree, if the community is willing to improve on that, it could definitely be a good data source for EVMap (though it will lead to fragmentation with some people contributing to GoingElectric, some to OpenChargeMap and some to OpenStreetMap...). https://wiki.openstreetmap.org/wiki/Overpass_API seems to have some information on the usage policy of the different Overpass API servers. For the ones where it is specified, the suggested limits are on the order of 1,000 to 10,000 requests per day. The app already has more than 10k users (I don't have statistics for F-Droid, but 10k from Google Play) and all users combined have generated ~60k requests per day to the GoingElectric API on average in the last month. So of course the number of people using OSM as a data source in EVMap would be lower initially, but in the long term we might put a significant load on these Overpass API servers. So we would probably need to either
And yes, finding out how fast these requests would be is definitely important.
Yep, I guess that would be the most stable way to go in the long term. The donations I receive from the app would however be just barely enough to to afford a small VPS, so probably far from something that could work for the OSM database... |
I'm not sure about how much the fragmentation will be since I think there are different motivations in order to contribute among at least of the mappers (as OpenStreetMap volunteers are called). As said, the asset of OpenStreetMap (OSM) is it's potentially large user base (see e.g. https://osmstats.neis-one.org/?item=countries&country=Switzerland ).
You could cache Overpass API results. |
Hm, that's actually not a bad idea, since it would avoid needing to download the full OSM planet file. However, this would require downloading the full dataset of charging stations, which might be larger than the overpass limits. I'll do a quick test to see how fast the planet data (only charging stations) can be extracted, and how large the dataset is currently. |
Actually, if the dataset is not too large, there's another alternative to the API which might even be way cooler: The server could preprocess the charging station data and host it as a regular static file in a compressed archive. The apps could then download that data (similar to the OSMand map data downloads) and would then work offline. This would require the implementation of an updater, but offline support is really nice and not API needs to be implemented. |
In the app dynamically during use - maybe. We do already do caching for GoingElectric (at least according to their caching rules, i.e. 24 hours), but that mainly affects the charger details and photos requests, not the requests for the list of chargers on the map, which are more difficult to cache due to server-side clustering and varying bounding boxes. On a server - yes, if the full dataset can be easily obtained through Overpass and is not too large. In the app with a single request download - yes, might also work depending on the dataset size. That might also be a good idea for other APIs (at least OpenChargeMap, who offer a single gzipped file for download - GoingElectric probably prohibits this in their API terms). |
I downloaded the OSM planet file (60 GiB) and ran Osmosis on it to extract all nodes with In an uncompressed "PostgreSQL dump" file, this is 16 MiB. Gzipped it's 3.4 MiB. Other output formats are possible as well, for example XML. Maybe we could even write a small conversion script that would output OpenChargingMap compatible JSON files (although non-preprocessed OSM-style raw key-value data might be better because it allows tweaking the filtering / data processing in the app without changing the data converter script). |
That sounds pretty manageable, so we could host that as a static gzipped file somewhere (maybe even on GitHub for now) and update it regularly. Of course it would be better if there were a script to update it through the Overpass API instead of by downloading 60 GiB of OSM data every time. I agree it probably makes sense to use OSM's own format (e.g. as JSON or XML) and build a separate API implementation for it in EVMap. You could start based on what is currently on the OpenChargeMap branch, but of course the implementation would need to look a bit different as the data would need to be downloaded and stored in a new table of the local database. |
Hi @johan12345, quick status update! The Swiss OSM Community's "Project of the Month" in September was focussed on adding and improving charging stations in OSM: https://wiki.openstreetmap.org/wiki/DE:Project_of_the_month_Switzerland/Charging_Stations Right now, there are 2251 charging stations in Switzerland, 370 of them were added last month (and hundreds of them were updated with more detailed information). Worldwide, there seem to be 57436 charging stations. I also spent some time improving the documentation in the Wiki, and I also created a JOSM Preset that simplifies the mapping of charging stations (right now with a Swiss focus which would need to be generalized). The work on this project of the month also led to an improved tagging schema for authentication and payment. The current status (limited to stations in Switzerland) can be viewed on this interactive map: https://umap.osm.ch/de/map/electromobility-charging-stations-in-switzerland-b_941#12/47.2731/8.7911
You're right, I'll try to create a test query for the Overpass API. This should give us JSON of all charging stations together with their metadata. |
Thanks for the update! 2251 charging stations in Switzerland brings OSM almost on the same level as GoingElectric (2774 stations), so this sounds pretty good.
Great 👍 Then I could create e.g. a separate GitHub repo with that JSON file and set up a cronjob to regularly update that. raw.githubusercontent.com already serves files gzipped, so that could be used as the URL to access the file. And then, if you would like to start the implementation in the app: I would suggest changing the |
Here's my PoC: https://github.com/dbrgn/evmap-osm The script currently takes roughly 6 minutes to fetch all 57437 charging stations via Overpass query (27 MiB of raw JSON) and writes them to a 2.8 MiB gzipped JSON. (When substituting Included data per charging station:
I hope this is helpful. If someone thinks that the format should be changed, feel free to let me know, I'm happy to adjust the script. Right now I don't know if I can promise an integration into EVMap, so if someone else has the time to do so, please go ahead! |
Thanks a lot! 👍 For development purposes I've set up your script on a temporary server that makes it available (served gzip-compressed) at The data format seems fine to me so far, just a few notes:
|
No, there is no validation or schema. Both keys and values are always strings.
Yeah, essentially the "schema" is a wiki page that recommends how to tag, so we always need to parse as loose/lenient as possible. To my knowledge, the proper format for output is Regarding the semicolon, I think this is for multiple outputs: {
"type": "node",
"id": 8219906320,
"lat": 69.5416905,
"lon": 20.5507106,
"timestamp": "2020-12-11T14:32:22Z",
"version": 1,
"changeset": 95686942,
"user": "NorNorth",
"uid": 420980,
"tags": {
"amenity": "charging_station",
"capacity": "5",
"fee": "yes",
"motorcar": "yes",
"name": "Ishavsveien Manndalen",
"operator": "Ishavsveien",
"socket:chademo": "2",
"socket:chademo:output": "100 kW;50 kW",
"socket:type2": "2",
"socket:type2:current": "32",
"socket:type2:output": "22 kW;22kW",
"socket:type2:voltage": "400",
"socket:type2_combo": "2",
"socket:type2_combo:output": "175 kW;50kW"
}
} This looks a bit weird to me. I suspect that these are actually two charging stations with different power outputs merged into one. Regarding the integration into EVMap, if the format cannot be parsed in a meaningful way, I'd simply ignore the key. In this case, we still know that there are two Type2, two CCS and two CHAdeMO outputs, that's already valuable information. Sometimes people also mapped plain numbers (e.g. There are also some fields tagged with
That is true. I think it's still valuable to see that there is a charging station there, but indicate that we have no information about the type of connectors or the output power. It might also be nice to show a note, saying that the data could be improved on OpenStreetMap. Since I have some experience with OSM tagging schemes, as a first step, would it help if I'd create a PR that can parse the dataset entries and convert them into some kind of domain object (together with unit tests)? I assume there are already classes to handle things like "charging station" and "output socket" and "output power", right? |
Okay, then we should keep it that way and handle the conversion within the app (and ignore the field if it doesn't conform to the expected format).
Yeah, I suspect that too - that is also typically done in the other data sources and is supported by EVMap. It simply makes sense to put chargers at the same site by the same operator into one entry, instead of mapping e.g. a Tesla Supercharger site with 20 stalls as 20 separate entries. So I think we should also try to parse this format (as long as the length of the list matches the number of plugs listed it should work).
Yeah, this would be great! The classes for this in EVMap are in this file (relevant ones should be So probably it makes sense to start from a class named e.g. |
To let the developer know that there are more people that would like to see OpenStreetMap as data source, i leave a 👍 |
I started working on the parsing and conversion code: https://github.com/dbrgn/EVMap/tree/osm Right now I only handle a single JSON entry. However, the current data source JSON file contains a top-level object with an "elements" array. While this is very flexible (we can easily add more fields later on), we cannot easily stream-process the entries. Thus, my suggestion would be to change the format from this {
"timestamp": 1642673932.142791,
"elements": [
{
"id": 8143993909,
"lat": -21.1283775,
...
},
...
]
} ...to a JSON-object-per-line based format: {"id": 8143993909, "lat": -21.1283775, ...}
{"id": 8149615093, "lat": -53.1657964, ...} If we want to retain the possibility to attach metadata, we could also put a meta-object on the first line: {"type": "metainfo", "timestamp": 1642673932, "total_count": 7342, ...} The parser would parse or skip the first line, and could then stream-process the rest. @johan12345 what are your thoughts on this? If you agree, I could update the evmap-osm script. The other topic is data storage and retrieval. How are current APIs handled? Is the data always loaded live from the API, filtered by the current viewbox, and then kept in memory? Or is the data stored/cached in the database? Is it a regular SQLite database, or can you use the SpatiaLite GIS extension? It would of course be preferrable if we can filter the loaded charging stations by viewbox. But for now, we could probably even fit all charging stations in memory, as long as we only load a subset of the data, i.e. id, lat/lng, and the speed (for the color). |
The evmap-osm script is updated: https://github.com/dbrgn/evmap-osm The output now looks like this: |
Thanks for the progress update, and sorry for the late reply! I think it is possible to process a large JSON array in a streaming-based fashion without changing to a line-based format with Moshi, the JSON parsing library that EVMap uses. For example, this post shows an example of that in the third part ("Coroutines magic for big data sources"). I'm not yet sure how to exactly integrate it with the HTTP request, but it should be doable.
Currently, the data is always loaded live from the API when panning the map. The
I think SpatiaLite is possible to use with Android's SQLite databases (e.g. I found https://github.com/anboralabs/spatia-room with a quick search), but for filtering by viewbox it might not even be necessary, as the viewbox can simply be given as a range of minimum and maximum latitude and longitude values, which we can use to query in the database. Of course, spatialite might later be needed e.g. for marker clustering or querying for the closest chargers to a specific location. |
I've added a proposal for restructuring the DB in #157 - with this change we'll be able to use the |
Very nice! I'll try to finish the parsing code this week. |
An initial version of the parser is almost done, only power parsing is left which should be fairly straightforward. During the implementation I decided to make |
Nice! Yes, it makes sense to make the power information nullable as it's not always available on OSM. Only regarding the conversion for the Chargeprice API I would rather have avoided to filter out chargepoints with But I'm not sure if Chargeprice will work with OSM data at all as they claim to only support GoingElectric and OpenChargeMap so far. |
Unfortunately I can't be of much help, since I'm not really familiar with neither SpatiaLite nor Room. I usually use PostGIS for geodatabase purposes 🙂 (Not on Android though, obviously.) With only around 60k charging stations, queries without an index might be fast enough. Spatia-Room looks interesting though. |
July 2021:
October 2021:
And I just ran the script again, by now there are 64100 charging stations, the number is increasing rapidly 🎉 I think with that OSM already contains roughly 4000 more charging stations than the GoingElectric database 🙂 |
Today I spent a couple of hours again to try and get spatia-room to work. Unfortunately it seems to only be a part of the solution: It does make it possible to create a database that uses SpatiaLite instead of Android's integrated SQLite binary, but it doesn't offer any support for actually creating entities that have geometry fields and mapping those to Spatialite tables. So even with spatia-room all fields are still required to be one of the default SQLite data types. And it looks like Room is not flexible enough to easily change this (as this would need changes to the compiler that generates the SQL queries at build time, not just the runtime component)... Other ideas:
|
Hmm, if this really cannot be integrated well with spatia-room, then this might be the best option:
However, I'll shamelessly ping @dalgarins, maybe he has an idea how to handle this with spatia-room? |
Hi, it's exciting to see that you are trying to use
and if you don't mind, share with me a little poc, I will review that a help to find a solution. Note: the next step for spatia-room it's create its own room compiler because the current compiler is limiting the library, if someone wants to join, let me know. |
@dalgarins Hey, thanks for your help! Creating an initial DB and loading that is not a good option in this case, as we need to migrate the data from the current database for existing app users. But I think I now have an idea how to solve it, I was just missing two key pieces of information:
I created a simple POC here: https://github.com/johan12345/SpatiaRoomTest - a first commit initializes the Room database without Spatialite (with simple double fields for lat and lng), and a second commit migrates it to Spatialite using spatia-room. @dalgarins does that look sensible to you or did I miss a more straightforward solution? I guess if this is how it is supposed to work, it would make sense to add such Geometry types (e.g. |
@johan12345 congrats for your work, I was reviewing the POC, everything looks working fine, I did the following test.
that was in the first commit, only to run the app.
Impressive job and you are right, it will be a great idea to have all this converters in spatia-room library, PR are welcome. |
I now take back my interest in OpenStreetMap support in EVMap. There is a simple reason why: |
Hi @johan12345, are there any news regarding OSM support? Is there anything I can do to help? |
Hi @dbrgn! Support for offline caching of chargers (using spatia-room) is pretty much finished in PR #164 - after a bit more testing I want to release a beta version of that soon. Currently it just caches the chargers that are loaded from the API in the local DB to avoid making repeated API calls for chargers/map regions which have already been loaded recently. So I think the next steps to add OSM support would be:
/**
* Whether this API supports querying for chargers at the backend
*
* This determines whether the getChargepoints, getChargepointsRadius and getChargepointDetail functions are supported.
*/
val supportsOnlineQueries: Boolean
/**
* Whether this API supports downloading the whole dataset into local storage
*
* This determines whether the getAllChargepoints function is supported.
*/
val supportsFullDownload: Boolean
/**
* Fetches all available chargers from this API.
*
* This may take a long time and should only be used when the user explicitly wants to download all chargers.
*
* TODO: add an optional callback parameter to this function to be able to receive updates on the download progress?
* TODO: Should this also include getting the ReferenceData, instead of taking it as an argument?
* ReferenceData typically includes information that is needed to create the filter options, e.g.
* mappings between IDs and readable names (for operators etc.). So probably for OSM it makes sense
* to generate that within this function (e.g. build the list of available operators using all the
* operators found in the dataset).
*/
suspend fun getAllChargepoints(referenceData: ReferenceData): List<ChargeLocation>
Does this sound good to you? Maybe if you have time, you could already start taking a look at the first two points. |
Hey @johan12345, sorry for not replying to your message from May... I thought I would have some time soon to help out, but we moved recently and I'm still swamped with other tasks that have higher priority 😅 I'll add some comments at #290. |
Please see Import wiki page for -required- guidelines and other information. |
Also, you should attribute "OpenStreetMap contributors" ("OpenStreetMap" is recommended but not required, the old version is still okay.) for data and (seperately) map data as needed. You should link "OpenStreetMap" to https://openstreetmap.org/copyright (the copyright page, please read it) if possible. Similarly, if using Mapbox, they require you to attribute them as well (see Documentation). |
Furthermore, I would like to suggest the following; Show the OpenStreetMap community what data you are using. Add EVMap to the list of Taginfo Projects. |
Yes, of course we are already doing that: EVMap/app/src/main/java/net/vonforst/evmap/api/openstreetmap/OpenStreetMapModel.kt Line 114 in 107ec10
Map data from Mapbox also displays the attribution logo provided by their library.
Thanks, I will look into that when OSM support (#290) is finished. |
OpenStreetMap has a tagging schema for charging stations: https://wiki.openstreetmap.org/wiki/Tag:amenity%3Dcharging_station It is the ideal database for this kind of data: It's a geo-database for objects with certain associated attributes.
What would it take to integrate OSM as a data source into EVMap? I assume excluding duplicates would be a challenge.
(PS: Very nice app, thanks for developing it!)
The text was updated successfully, but these errors were encountered: