autodesk-platform-services / aps-iot-extensions-demo

APS DataViz Extensions Demo:Visualizing IoT sensor data.
https://aps-iot-extensions-demo.autodesk.io
MIT License
11 stars 6 forks source link

Can't change the start and end date of the timeSlider #13

Closed amelnait closed 11 months ago

amelnait commented 11 months ago

Hello, I have a question regarding a project you've developed, "aps-iot-extensions-demo." I'm currently working on it, but I've encountered an issue. When I add date boxes in the viewer, the timeSlider of the app doesn't seem to change based on the dates that the user selects. It's as if the timeslider.on('tsmodifystart', (ev) => { console.log('tsmodifystart'); }); isn't functioning as expected. Do you have any recommendations on how to fix this issue? thank you

yiskang commented 11 months ago

For caching time range changed event, you should use tsmodified instead, not tsmodifystart.

timeSliderControl.on("tsmodified", onTimeRangeUpdated);

ref: https://github.com/Autodesk-Forge/forge-dataviz-iot-react-components/blob/b7d398ff358a9145847d091ceff8db124f5d88ec/client/components/ChronosTimeSlider.jsx#L150

amelnait commented 11 months ago

When launching the "tsmodified" application, it doesn't work. I also tried to use a console.log() to see if there would be any changes, but it didn't work either. The only events that are working are "tscreated," "timemarkerchanged," and "playbackmarkerchanged." These events correspond to either a more precise date selection or when the timeslider is launched.

I have defined the dates as follows: startDate = datepicker(".start", { id: 1, startDate, dateSelected: startDate, onSelect: handleDateSelect_start, });

endDate = datepicker(".end", { id: 1, endDate, dateSelected: endDate, onSelect: handleDateSelect_end, }); this line doesn't work : timeslider.on( "tsmodified", debounce((ev) => { console.log(" event "); onTimeRangeChanged(new Date(ev.start), new Date(ev.end)); }) );

yiskang commented 11 months ago

Have you assigned new date value to timeSlider? I might miss that, but I didn't see that in your code snippet.

let start = new Date(data.start);
let end = new Date(data.end);
timeSlider.mStartTime = start;
timeSlider.mEndTime = end;

Ref: https://github.com/Autodesk-Forge/forge-dataviz-iot-react-components/blob/b7d398ff358a9145847d091ceff8db124f5d88ec/client/components/ChronosTimeSlider.jsx#L131

amelnait commented 11 months ago

import "./extensions.js"; import { initViewer, loadModel, adjustPanelStyle } from "./viewer.js"; import { initTimeline } from "./timeline.js"; import { MyDataView } from "./dataview.js"; import "./sensormanager.js";

const FORGE_MODEL_VIEW = ""; const RESOLUTION = 15;

const IOT_EXTENSION_IDS = [ "IoT.SensorList", "IoT.SensorDetail", "IoT.SensorSprites", "IoT.DataGrid", "IoT.SensorHeatmaps", ];

const IOT_PANEL_STYLES = { "IoT.SensorList": { right: "10px", top: "50px", width: "700px", height: "auto", // resize: "both", // marginBottom: "0em", }, "IoT.SensorHeatmaps": { left: "10px", top: "320px", width: "300px", height: "150px", }, };

const currentDate = new Date(); currentDate.setUTCHours(0, 0, 0, 0);

var endDate = new Date(currentDate.getTime()); endDate.setUTCHours(0, 0, 0, 0);

var startDate = new Date(currentDate.getTime() - 3 24 60 60 1000); startDate.setUTCHours(0, 0, 0, 0);

const timeSlider = await initTimeline( document.getElementById("timeline"), onTimeRangeChanged, onTimeMarkerChanged, startDate, endDate );

let dataView = new MyDataView(); await dataView.init( { start: startDate, end: endDate, }, RESOLUTION );

let all_dataView = new MyDataView(); await all_dataView.init( { start: startDate, end: endDate, }, RESOLUTION );

let extensions = [];

/**

async function onTimeRangeChanged(start, end, RESOLUTION) { await dataView.refresh({ start, end }, RESOLUTION); extensions.forEach((ext) => (ext.dataView = dataView)); }

/**

function onTimeMarkerChanged(time) { extensions.forEach((ext) => (ext.currentTime = time)); }

function onCurrentChannelChanged(channelId) { extensions.forEach((ext) => (ext.currentChannelID = channelId)); }

/**

const viewer = await initViewer( document.getElementById("preview"), IOT_EXTENSION_IDS.concat(["Iot.SensorManager"]) );

async function handleDateSelect_start(start, RESOLUTION) { timeSlider.mStartTime = start.dateSelected;

startDate = start.dateSelected;

onTimeRangeChanged(startDate, endDate, RESOLUTION); } async function handleDateSelect_end(end, RESOLUTION) { timeSlider.mEndTime = end.dateSelected; timelineTest.end = end.dateSelected; endDate = end.dateSelected;

onTimeRangeChanged(startDate, endDate, RESOLUTION); } async function onModelSelected(typeOfsensor) { extensions = []; // Setup and auto-activate IoT extensions for (const extensionID of IOT_EXTENSION_IDS) { const extension = viewer.getExtension(extensionID); extensions.push(extension); var test2 = all_dataView.getSensors(); var sensorMap = new Map(); var myMap = new Map(); let all_channels = Array.from(all_dataView.getChannels().keys());

let channelNames = all_channels.filter(function (channel) {
  return channel.startsWith(typeOfsensor);
});

for (var channelName of channelNames) {
  var channels = all_dataView.getChannels().get(channelName);
  myMap.set(channelName, channels);
}

test2.forEach((sensor) => {
  if (channelNames.includes(sensor.description)) {
    sensorMap.set(sensor.code, sensor);
  }
});

dataView._channels = myMap;
dataView._sensorsFilteredByFloor = sensorMap;

extension.dataView = dataView;
extension.activate();

if (IOT_PANEL_STYLES[extensionID]) {
  adjustPanelStyle(extension.panel, IOT_PANEL_STYLES[extensionID]);
}

} } async function setupModelSelection(typeSensors, selectedUrn) { const dropdown = document.getElementById("models"); try { dropdown.innerHTML = typeSensors .map( (model) => <option value=${model} ${ model === selectedUrn ? "selected" : "" }>${model}</option> ) .join("\n"); // ajouter du style au dropdown dropdown.classList.add("custom-dropdown"); dropdown.onchange = () => { onModelSelected(dropdown.value); }; } catch (err) { alert("Could not list models. See the console for more details."); console.error(err); } } function getSpritesPositions() { return new Promise((resolve, reject) => { fetch("/getDbids") .then((response) => { if (!response.ok) { throw new Error("Réponse du serveur non valide"); }

    return response.json();
  })
  .then((dbids) => {
    // Traiter les dbids reçus depuis le backend

    dbids = dbids.map((dbid) => parseInt(dbid, 10));

    // get dbids of the viewer
    var fragIds = viewer.model.getData().instanceTree;
    // dbIds is all the dbis of all the objects in the viewer
    var dbIds = Object.keys(fragIds.nodeAccess.dbIdToIndex);
    var copy_dbIds_selected = [
      1233,2345?3456,245
    ];
    const tree = viewer.model.getInstanceTree();
    const frags = viewer.model.getFragmentList();
    let test2 = [];
    if (tree) {
      dbids.map((dbId) => {
        var fragIds = [];
        tree.enumNodeFragments(
          dbId,
          (fragId) => {
            fragIds.push(fragId);
          },
          false
        );

        let matrix = new THREE.Matrix4();
        frags.getWorldMatrix(fragIds, matrix);
        let bbox = new THREE.Box3();

        frags.getWorldBounds(fragIds[0], bbox);
        const x = (bbox.max.x + bbox.min.x) / 2;
        const y = (bbox.max.y + bbox.min.y) / 2;
        const z = (bbox.max.z + bbox.min.z) / 2;
        test2.push({
          id: dbId,
          code: "1",
          name: "",
          description: "",
          groupName: "",
          location: {
            x: x,
            y: y,
            z: z,
          },
          objectId: dbId,
        });
      });
    }

    resolve(test2); // Résoudre la promesse avec les données
  })
  .catch((error) => {
    console.error("Erreur lors de la récupération des dbids :", error);
    reject(error); // Rejeter la promesse en cas d'erreur
  });

}); }

var FORGE_MODEL_URN;

fetch("/api/config") .then((response) => response.json()) .then((data) => { FORGE_MODEL_URN = data.apiKey; loadModel(viewer, FORGE_MODEL_URN, FORGE_MODEL_VIEW); }) .catch((error) => { console.error("Erreur lors de la récupération des données :", error); });

viewer.addEventListener( Autodesk.Viewing.GEOMETRY_LOADED_EVENT, async function (timeSlider) { var typeSensors = []; const sensors = dataView.getSensors(); sensors.forEach((sensor) => { if (!typeSensors.includes(sensor.description)) { typeSensors.push(sensor.description); } });

let sensorlist = document.getElementById("iot-sensor-list");
let styleSensor = sensorlist.querySelector("[style]");
styleSensor.style = "";
styleSensor.style.left = "";

let doc = document.getElementById("preview");
if (doc) {
  setupModelSelection(typeSensors, "Pressure");
}

const spritesData = await getSpritesPositions();

var db = JSON.stringify(spritesData);
// console.log('db :',db)
fetch("/api/getData?content=" + db)
  .then((res) => res.json())
  .catch((e) => {
    console.log("Err: ", e);
  });

startDate = datepicker(".start", {
  id: 1,
  startDate,
  dateSelected: startDate,
  onSelect: handleDateSelect_start,
});
endDate = datepicker(".end", {
  id: 1,
  endDate,
  dateSelected: endDate,
  onSelect: handleDateSelect_end,
});

startDate = startDate.dateSelected;
endDate = endDate.dateSelected;
let defaultSesor = "Pressure";
onModelSelected(defaultSesor);

onTimeRangeChanged(startDate, endDate, RESOLUTION);

viewer.getExtension("IoT.SensorList").onSensorClicked = (sensorId) =>
  onCurrentSensorChanged(sensorId);
viewer.getExtension("IoT.SensorSprites").onSensorClicked = (sensorId) => {
  onCurrentSensorChanged(sensorId);
};
// viewer.getExtension("IoT.DataGrid").onSensorClicked = (sensorId) => {
//   onCurrentSensorChanged(sensorId);
// };
viewer.getExtension("IoT.SensorHeatmaps").onChannelChanged = (channelId) =>
  onCurrentChannelChanged(channelId);

} );

Here is the code of the file where I declared these 2 lines timeSlider.mStartTime = start; timeSlider.mEndTime = end; but I don't understand why it still doesn't trigger tsmodified if you have an idea why this is happening please tell me how to fix it