#ifndef WIFIMODELPERFLOOR_H #define WIFIMODELPERFLOOR_H #include "../AccessPoint.h" #include "../../../geo/Point3.h" #include #include "WiFiModelFactory.h" /** * FOR TESTING * * this model allows using a different sub-models for each floor to reduce the error */ class WiFiModelPerFloor : public WiFiModel { struct ModelForFloor { float fromZ; float toZ; WiFiModel* mdl; /** ctor */ ModelForFloor(const float fromZ, const float toZ, WiFiModel* mdl) : fromZ(fromZ), toZ(toZ), mdl(mdl) {;} /** does this entry apply to the given z-position? */ bool matches(const float z) const { return (fromZ <= z && z < toZ); } }; Floorplan::IndoorMap* map; /** all contained models [one per floor] */ std::vector models; public: WiFiModelPerFloor(Floorplan::IndoorMap* map) : map(map) { ; } /** dtor */ virtual ~WiFiModelPerFloor() { } /** get a list of all APs known to the model */ std::vector getAllAPs() const override { return models.front().mdl->getAllAPs(); } void add(WiFiModel* mdl, const Floorplan::Floor* floor) { ModelForFloor mff(floor->atHeight, floor->atHeight+floor->height, mdl); models.push_back(mff); } float getRSSI(const MACAddress& accessPoint, const Point3 position_m) const override { for (const ModelForFloor& mff : models) { if (mff.matches(position_m.z)) {return mff.mdl->getRSSI(accessPoint, position_m);} } return -120; } void readFromXML(XMLDoc* doc, XMLElem* src) override { // check type if (std::string("WiFiModelPerFloor") != src->Attribute("type")) {throw Exception("invalid model type");} models.clear(); // model factory [create models based on XMl content] WiFiModelFactory fac(map); // parse all contained models [one per floor] XML_FOREACH_ELEM_NAMED("floor", xfloor, src) { // floor params const float z1 = xfloor->FloatAttribute("z1"); const float z2 = xfloor->FloatAttribute("z2"); // node for the model XMLElem* xmodel = xfloor->FirstChildElement("model"); // let the factory instantiate the model WiFiModel* mdl = fac.readFromXML(doc, xmodel); // add models.push_back(ModelForFloor(z1, z2, mdl)); } } void writeToXML(XMLDoc* doc, XMLElem* dst) override { // set my type dst->SetAttribute("type", "WiFiModelPerFloor"); for (const ModelForFloor& mff : models) { XMLElem* xfloor = doc->NewElement("floor"); { xfloor->SetAttribute("z1", mff.fromZ); xfloor->SetAttribute("z2", mff.toZ); XMLElem* xmodel = doc->NewElement("model"); { mff.mdl->writeToXML(doc, xmodel); }; xfloor->InsertEndChild(xmodel); }; dst->InsertEndChild(xfloor); } } }; #endif // WIFIMODELPERFLOOR_H