Good Day
I'm confused about this issue, I have a websocket that is returning data to me. ex:
{
features:[{
"geometry": {
"x": -8841036.030462436,
"y": 5471327.551341704
},
"attributes": {
"objectId": 31311,
"assetTypeId": 14,
"assetSectionId": 31311,
"assetId": "ST3472",
"name": "Silly Face Circle",
"gisId": "ST11111",
"assetStatus": "In-service",
"installationYear": 2010,
"replacementCost": 8800,
"replacementCostYear": 2021,
"costAdjustmentFactor": 1,
"fixedCost": 0,
"exclude": "No",
"material": "Something",
"count": 1,
"owner": "Me",
"condition": 86.3,
"sl": "80.00",
"rsl": "69.00",
"decisionClass": "Something Something",
"degradationClass": "Something Something",
"performanceClass": "blah - face,
"criticality": 50,
"risk": 6
}
}],
type: "features"
}
I have the fields setup as:
[
{
"name": "objectId",
"alias": "objectId",
"type": "oid"
},
{
"name": "assetTypeId",
"alias": "assetTypeId",
"type": "double"
},
{
"name": "assetSectionId",
"alias": "assetSectionId",
"type": "double"
},
{
"name": "assetId",
"alias": "assetId",
"type": "string"
},
{
"name": "gisId",
"alias": "gisId",
"type": "string"
},
{
"name": "name",
"alias": "name",
"type": "string"
},
{
"name": "assetStatus",
"alias": "assetStatus",
"type": "string"
},
{
"name": "installationYear",
"alias": "installationYear",
"type": "double"
},
{
"name": "length",
"alias": "length",
"type": "double"
},
{
"name": "area",
"alias": "area",
"type": "double"
},
{
"name": "volume",
"alias": "volume",
"type": "double"
},
{
"name": "quantity",
"alias": "quantity",
"type": "double"
},
{
"name": "replacementCost",
"alias": "replacementCost",
"type": "double"
},
{
"name": "replacementCostYear",
"alias": "replacementCostYear",
"type": "double"
},
{
"name": "costAdjustmentFactor",
"alias": "costAdjustmentFactor",
"type": "double"
},
{
"name": "fixedCost",
"alias": "fixedCost",
"type": "double"
},
{
"name": "exclude",
"alias": "exclude",
"type": "string"
},
{
"name": "zone",
"alias": "zone",
"type": "string"
},
{
"name": "diameter",
"alias": "diameter",
"type": "double"
},
{
"name": "depth",
"alias": "depth",
"type": "double"
},
{
"name": "rimElevation",
"alias": "rimElevation",
"type": "double"
},
{
"name": "coverDiameter",
"alias": "coverDiameter",
"type": "double"
},
{
"name": "numberofPipesIn",
"alias": "numberofPipesIn",
"type": "double"
},
{
"name": "numberofPipesOut",
"alias": "numberofPipesOut",
"type": "double"
},
{
"name": "soilType",
"alias": "soilType",
"type": "string"
},
{
"name": "soilCondition",
"alias": "soilCondition",
"type": "string"
},
{
"name": "classification",
"alias": "classification",
"type": "string"
},
{
"name": "material",
"alias": "material",
"type": "string"
},
{
"name": "roadsideEnvironment",
"alias": "roadsideEnvironment",
"type": "string"
},
{
"name": "functionalClass",
"alias": "functionalClass",
"type": "string"
},
{
"name": "coverType",
"alias": "coverType",
"type": "string"
},
{
"name": "serviceType",
"alias": "serviceType",
"type": "string"
},
{
"name": "overflowWeir",
"alias": "overflowWeir",
"type": "string"
},
{
"name": "risk",
"alias": "risk",
"type": "double"
},
{
"name": "criticality",
"alias": "criticality",
"type": "double"
},
{
"name": "performanceClass",
"alias": "performanceClass",
"type": "string"
},
{
"name": "decisionClass",
"alias": "decisionClass",
"type": "string"
},
{
"name": "initialCost",
"alias": "initialCost",
"type": "double"
},
{
"name": "defectFlag",
"alias": "defectFlag",
"type": "string"
},
{
"name": "count",
"alias": "count",
"type": "double"
},
{
"name": "owner",
"alias": "owner",
"type": "string"
},
{
"name": "showOnCapitalPlan",
"alias": "showOnCapitalPlan",
"type": "string"
},
{
"name": "groupIDCorridorID",
"alias": "groupIDCorridorID",
"type": "string"
},
{
"name": "degradationClass",
"alias": "degradationClass",
"type": "string"
},
{
"name": "formulaGroup",
"alias": "formulaGroup",
"type": "string"
},
{
"name": "condition",
"alias": "condition",
"type": "double"
},
{
"name": "sl",
"alias": "sl",
"type": "double"
},
{
"name": "rsl",
"alias": "rsl",
"type": "double"
}
]
The StreamLayer object is:
return new StreamLayer({ fields: fields, geometryType: geometry, id: streamLayerId, maxReconnectionAttempts: 500, maxReconnectionInterval: 500, objectIdField: 'objectId', renderer: renderSetting, timeInfo: { trackIdField: "assetSectionId" }, webSocketUrl: `${webSocketAPI}api/MapStream/stream` })
Which is how I'm creating 20+ other layers that show up correctly. This one layer won't show up, doesn't list any features, and it should have ~3000, BUT, doesn't list any errors, or warnings, and will return it's "Loaded". Is there any way to get additional information? I'm assuming something in the data is bad, but shouldn't that generate a warning or error? in loadWarings / loadErrors?
Thanks for any help
Cheers
Solved! Go to Solution.
Hey @AndrewMurdoch1 ! There's not really a good way to query all features on the layer. Unlike for feature layer, the stream layer doesn't have a queryFeatures() method, and StreamLayerView.queryFeatures() will only return features available for drawing.
If I'm understanding your use case correctly, I think the best option would probably be to listen for the "data-received" event on the layer view. That can tell you when data first arrives, even if it's outside of frame. Here's a codepen, maybe something like this would work? https://codepen.io/sam11948/pen/jEOZoYQ
Hey @AndrewMurdoch1! It's hard to say what might be going on from your description. If this pattern works for other layers, then it sounds like something might be configured incorrectly in the service. If you check the network tab of your browser's dev tools, do you see any communication with the web socket? Are you able to connect to the service manually?
So the output I posted is returned to the StreamLayer from the Web Socket, and all the other layers have the same structure, so I'm perplexed.
The render setting seems fine, the geometry seems fine, the attributes, and fields seem valid, so do you know if there's away to get better logging information from the StreamLayer? When I look at Load Warnings or Load Errors, I have none, which would tell me the data was / is fine because I don't know what else to take from that.
I would suspect something must provide me debugging information as the features are loaded from the Web Socket into the StreamLayer.
Thanks
There's not a verbose log, no. You could check a few properties on the layer view, like connectionStatus , connectionError , and the data-received and message-received events (though perhaps that's where you got the output you posted).
It also might be worth double checking that the purgeOptions and updateInterval are configured correctly on the layer. And you can always check things by passing data directly into a client-side stream layer (more here under "Add an array of client-side features" ).
It'd be helpful to see the problem isolated in a codepen or app.
Good Afternoon
I think I finally found the issue! To make sure I run the progress spinner until features are on the map, I'm using an interval to carry out the following steps (generalized):
1. Wait for the Layer View
2. Build a query to find features in the Layer View
3. Run "queryFeatures"
4. If the feature count returned is >= 1, then stop the spinner.
The issue is if my view extent doesn't contain any features it won't get updated, because if I zoom out they pop in. if I have the following code:
const query = {
geometry: this._view.extent.clone().expand(100),
outFields: ['*'],
where: '1=1'
}
layerView.queryFeatures(query).then((features) => {
if (features.features.length) {
clearInterval(waitForFeatures)
this.layerLoadedEvent.emit(true);
}
})
How can I check the entire map?
Thanks
Hey @AndrewMurdoch1 ! There's not really a good way to query all features on the layer. Unlike for feature layer, the stream layer doesn't have a queryFeatures() method, and StreamLayerView.queryFeatures() will only return features available for drawing.
If I'm understanding your use case correctly, I think the best option would probably be to listen for the "data-received" event on the layer view. That can tell you when data first arrives, even if it's outside of frame. Here's a codepen, maybe something like this would work? https://codepen.io/sam11948/pen/jEOZoYQ
That's precisely what I'm trying to do! Thanks for the help