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

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

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

Closed amelnait closed 1 year ago

amelnait commented 1 year 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 1 year 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 1 year 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 1 year 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 1 year 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