Skip to content

Commit

Permalink
Merge pull request #385 from energywebfoundation/feat/registration-form
Browse files Browse the repository at this point in the history
Device registration
  • Loading branch information
e00dan authored Dec 19, 2019
2 parents 094bd6c + b5084d9 commit 47de89c
Show file tree
Hide file tree
Showing 61 changed files with 1,880 additions and 968 deletions.
7 changes: 6 additions & 1 deletion packages/device-registry/contracts/DeviceDefinitions.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
pragma solidity ^0.5.2;

contract DeviceDefinitions {
enum DeviceStatus {
Submitted,
Denied,
Active
}

enum UsageType {
Producing,
Expand All @@ -12,7 +17,7 @@ contract DeviceDefinitions {
address smartMeter;
address owner;
uint lastSmartMeterReadWh;
bool active;
DeviceStatus status;
string lastSmartMeterReadFileHash;
string propertiesDocumentHash;
string url;
Expand Down
110 changes: 32 additions & 78 deletions packages/device-registry/contracts/DeviceLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,18 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {

event LogDeviceCreated(address _sender, uint indexed _deviceId);
event LogDeviceFullyInitialized(uint indexed _deviceId);
event LogDeviceSetActive(uint indexed _deviceId);
event LogDeviceSetInactive(uint indexed _deviceId);
event DeviceStatusChanged(uint indexed _deviceId, DeviceDefinitions.DeviceStatus _status);
event LogNewMeterRead(
uint indexed _deviceId,
uint _oldMeterRead,
uint _newMeterRead,
uint _timestamp
);

/// @dev mapping for smartMeter-address => Device
mapping(address => DeviceDefinitions.Device) internal _deviceMapping;
mapping(address => DeviceDefinitions.SmartMeterRead[]) internal _deviceSmartMeterReadsMapping;
DeviceDefinitions.Device[] private allDevices;

/// @dev list of all the smartMeters already used
address[] internal _smartMeterAddresses;
/// @dev mapping for device id => smart meter reads
mapping(uint => DeviceDefinitions.SmartMeterRead[]) internal _deviceSmartMeterReadsMapping;

/// @notice constructor
function initialize(address userLogicAddress) public initializer {
Expand Down Expand Up @@ -60,20 +57,13 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {
return getDeviceById(_deviceId);
}

/// @notice Sets active to false
/// @param _deviceId The id belonging to an entry in the device registry
/// @param _active flag if the device is device or not
function setActive(uint _deviceId, bool _active)
function setStatus(uint _deviceId, DeviceDefinitions.DeviceStatus _status)
external
onlyRole(RoleManagement.Role.DeviceAdmin)
onlyRole(RoleManagement.Role.Issuer)
{
_deviceMapping[_smAddressForDeviceId(_deviceId)].active = _active;
allDevices[_deviceId].status = _status;

if (_active) {
emit LogDeviceSetActive(_deviceId);
} else {
emit LogDeviceSetInactive(_deviceId);
}
emit DeviceStatusChanged(_deviceId, _status);
}

/// @notice Logs meter read
Expand All @@ -99,47 +89,54 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {

uint createdEnergy = _setSmartMeterRead(_deviceId, _newMeterRead, _lastSmartMeterReadFileHash, timestamp);

_deviceSmartMeterReadsMapping[_smAddressForDeviceId(_deviceId)].push(
_deviceSmartMeterReadsMapping[_deviceId].push(
DeviceDefinitions.SmartMeterRead({ energy: createdEnergy, timestamp: timestamp })
);
}

/// @notice creates an device with the provided parameters
/// @param _smartMeter smartmeter of the device
/// @param _owner device-owner
/// @param _active flag if the device is already active
/// @param _status device status
/// @param _usageType consuming or producing device
/// @param _propertiesDocumentHash hash of the document with the properties of an device
/// @param _url where to find the documentHash
/// @return generated device-id
function createDevice(
address _smartMeter,
address _owner,
bool _active,
DeviceDefinitions.DeviceStatus _status,
DeviceDefinitions.UsageType _usageType,
string calldata _propertiesDocumentHash,
string calldata _url
) external returns (uint deviceId) {
_checkBeforeCreation(_owner, _smartMeter);
require(isRole(RoleManagement.Role.DeviceManager, _owner), "device owner has to have device manager role");
require(
_owner == msg.sender ||
isRole(RoleManagement.Role.DeviceAdmin, msg.sender) ||
isRole(RoleManagement.Role.Issuer, msg.sender),
"only device admin and issuer can create a device for different owner"
);
require(
_status == DeviceDefinitions.DeviceStatus.Submitted ||
isRole(RoleManagement.Role.DeviceAdmin, msg.sender) ||
isRole(RoleManagement.Role.Issuer, msg.sender), "only admin and issuer can add devices with status other than submitted"
);

DeviceDefinitions.Device memory _device = DeviceDefinitions.Device({
smartMeter: _smartMeter,
owner: _owner,
lastSmartMeterReadWh: 0,
active: _active,
status: _status,
usageType: _usageType,
lastSmartMeterReadFileHash: "",
propertiesDocumentHash: _propertiesDocumentHash,
url: _url
});

deviceId = _smartMeterAddresses.length;

address smartMeter = _device.smartMeter;
deviceId = allDevices.length;

_deviceMapping[smartMeter] = _device;

_smartMeterAddresses.push(smartMeter);
allDevices.push(_device);
emit LogDeviceCreated(msg.sender, deviceId);
}

Expand All @@ -160,28 +157,14 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {
function getSmartMeterReadsForDevice(uint _deviceId) public view
returns (DeviceDefinitions.SmartMeterRead[] memory reads)
{
return _deviceSmartMeterReadsMapping[_smAddressForDeviceId(_deviceId)];
return _deviceSmartMeterReadsMapping[_deviceId];
}

/// @notice Gets an device
/// @param _deviceId The id belonging to an entry in the device registry
/// @return Full informations of an device
function getDeviceById(uint _deviceId) public view returns (DeviceDefinitions.Device memory) {
return _deviceMapping[_smAddressForDeviceId(_deviceId)];
}

/// @notice gets an device by its smartmeter
/// @param _smartMeter smartmeter used for by the device
/// @return Device-Struct
function getDeviceBySmartMeter(address _smartMeter) public view returns (DeviceDefinitions.Device memory) {
return _deviceMapping[_smartMeter];
}

/// @notice checks whether an devices with the provided smartmeter already exists
/// @param _smartMeter smart meter address of an device
/// @return whether there is already an device with that smartmeter
function checkDeviceExist(address _smartMeter) public view returns (bool) {
return _checkDeviceExistingStatus(getDeviceBySmartMeter(_smartMeter));
return allDevices[_deviceId];
}

/// @notice gets the owner-address of an device
Expand All @@ -206,35 +189,14 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {
/// @notice function to get the amount of already onboarded devices
/// @return the amount of devices already deployed
function getDeviceListLength() public view returns (uint) {
return _smartMeterAddresses.length;
return allDevices.length;
}


/**
Internal functions
*/

function _smAddressForDeviceId(uint _deviceId) internal view returns (address) {
require(_deviceId < getDeviceListLength(), "getDeviceById: invalid device ID");

return _smartMeterAddresses[_deviceId];
}

/// @notice checks whether an Device-struct already exists
/// @param _device the Device-struct
/// @return whether that struct exists
function _checkDeviceExistingStatus(DeviceDefinitions.Device memory _device) internal pure returns (bool) {
return !(
address(_device.smartMeter) == address(0x0)
&& address(_device.owner) == address(0x0)
&& _device.lastSmartMeterReadWh == 0
&& !_device.active
&& bytes(_device.lastSmartMeterReadFileHash).length == 0
&& bytes(_device.propertiesDocumentHash).length == 0
&& bytes(_device.url).length == 0
);
}

/// @notice sets a new meterreading for an device
/// @param _deviceId the id of an device
/// @param _newMeterRead the new meterreading in Wh
Expand All @@ -245,15 +207,16 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {
string memory _smartMeterReadFileHash,
uint _timestamp
) internal returns (uint) {
DeviceDefinitions.Device storage device = _deviceMapping[_smAddressForDeviceId(_deviceId)];
DeviceDefinitions.Device storage device = allDevices[_deviceId];
require(device.smartMeter == msg.sender, "saveSmartMeterRead: wrong sender");
require(device.active, "saveSmartMeterRead: device not active");

uint oldMeterRead = device.lastSmartMeterReadWh;

/// @dev need to check if new meter read is higher then the old one
require(_newMeterRead > oldMeterRead, "saveSmartMeterRead: meter read too low");

require(device.status == DeviceDefinitions.DeviceStatus.Active, "saveSmartMeterRead: device not active");

device.lastSmartMeterReadWh = _newMeterRead;
device.lastSmartMeterReadFileHash = _smartMeterReadFileHash;

Expand All @@ -266,13 +229,4 @@ contract DeviceLogic is Initializable, RoleManagement, IDeviceLogic {

return (_newMeterRead-oldMeterRead);
}

/// @notice runs some checks before creating an device
/// @param _owner the address of the device-owner
/// @param _smartMeter the smartmeter used by that device
function _checkBeforeCreation(address _owner, address _smartMeter) internal view {
require(isRole(RoleManagement.Role.DeviceManager, _owner), "user does not have the required role");
require(isRole(RoleManagement.Role.DeviceAdmin, msg.sender), "user does not have the required role");
require(!checkDeviceExist(_smartMeter), "smartmeter does already exist");
}
}
23 changes: 6 additions & 17 deletions packages/device-registry/contracts/IDeviceLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ contract IDeviceLogic {

event LogDeviceCreated(address _sender, uint indexed _deviceId);
event LogDeviceFullyInitialized(uint indexed _deviceId);
event LogDeviceSetActive(uint indexed _deviceId);
event LogDeviceSetInactive(uint indexed _deviceId);
event DeviceStatusChanged(uint indexed _deviceId, DeviceDefinitions.DeviceStatus _status);
event LogNewMeterRead(
uint indexed _deviceId,
uint _oldMeterRead,
Expand All @@ -27,10 +26,10 @@ contract IDeviceLogic {
/// @return the Device-struct as memory
function getDevice(uint _deviceId) external view returns (DeviceDefinitions.Device memory device);

/// @notice Sets active to false
/// @notice Sets status
/// @param _deviceId The id belonging to an entry in the device registry
/// @param _active flag if the device is device or not
function setActive(uint _deviceId, bool _active) external;
/// @param _status device status
function setStatus(uint _deviceId, DeviceDefinitions.DeviceStatus _status) external;

/// @notice Logs meter read
/// @param _deviceId The id belonging to an entry in the device registry
Expand All @@ -45,15 +44,15 @@ contract IDeviceLogic {
/// @notice creates an device with the provided parameters
/// @param _smartMeter smartmeter of the device
/// @param _owner device-owner
/// @param _active flag if the device is already active
/// @param _status device status
/// @param _usageType consuming or producing device
/// @param _propertiesDocumentHash hash of the document with the properties of an device
/// @param _url where to find the documentHash
/// @return generated device-id
function createDevice(
address _smartMeter,
address _owner,
bool _active,
DeviceDefinitions.DeviceStatus _status,
DeviceDefinitions.UsageType _usageType,
string calldata _propertiesDocumentHash,
string calldata _url) external returns (uint deviceId);
Expand All @@ -66,16 +65,6 @@ contract IDeviceLogic {
/// @return Full informations of an device
function getDeviceById(uint _deviceId) public view returns (DeviceDefinitions.Device memory);

/// @notice gets an device by its smartmeter
/// @param _smartMeter smartmeter used for by the device
/// @return Device-Struct
function getDeviceBySmartMeter(address _smartMeter) public view returns (DeviceDefinitions.Device memory);

/// @notice checks whether an devices with the provided smartmeter already exists
/// @param _smartMeter smart meter address of an device
/// @return whether there is already an device with that smartmeter
function checkDeviceExist(address _smartMeter) public view returns (bool);

/// @notice gets the owner-address of an device
/// @param _deviceId the id of an device
/// @return the owner of that device
Expand Down
2 changes: 1 addition & 1 deletion packages/device-registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"test": "test"
},
"scripts": {
"build": "yarn build:ts",
"build": "yarn build:static && yarn build:ts",
"build:static": "yarn compile && yarn extractABI && yarn build-schemas",
"build:ts": "tsc -b tsconfig.build.json --verbose --pretty",
"build-and-deploy": "yarn build && yarn deploy-contracts",
Expand Down
30 changes: 18 additions & 12 deletions packages/device-registry/src/blockchain-facade/ConsumingDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const createDevice = async (
const tx = await configuration.blockchainProperties.deviceLogicInstance.createDevice(
deviceProperties.smartMeter.address,
deviceProperties.owner.address,
deviceProperties.active,
deviceProperties.status,
Device.UsageType.Consuming,
deviceProperties.propertiesDocumentHash,
deviceProperties.url,
Expand All @@ -45,20 +45,26 @@ export const createDevice = async (
};

export const getAllDevices = async (configuration: Configuration.Entity): Promise<Entity[]> => {
const deviceLogicInstance = configuration.blockchainProperties.deviceLogicInstance;
const { deviceLogicInstance } = configuration.blockchainProperties;
const deviceListLength = parseInt(await deviceLogicInstance.getDeviceListLength(), 10);

const devicesPromises = Array(deviceListLength).fill(null).map(async (item, index) => {
return {
id: index,
device: await deviceLogicInstance.getDevice(index)
};
});
const devicesPromises = Array(deviceListLength)
.fill(null)
.map(async (item, index) => {
return {
id: index,
device: await deviceLogicInstance.getDevice(index)
};
});

const allDevices = await Promise.all(devicesPromises);

const consumingDevices = allDevices.filter((device, index) => Number(device.device.usageType) === Device.UsageType.Consuming);
const consumingDevicesSynced = consumingDevices.map(device => new Entity(device.id.toString(), configuration).sync());
const consumingDevices = allDevices.filter(
(device, index) => Number(device.device.usageType) === Device.UsageType.Consuming
);
const consumingDevicesSynced = consumingDevices.map(device =>
new Entity(device.id.toString(), configuration).sync()
);

return Promise.all(consumingDevicesSynced);
};
Expand All @@ -75,7 +81,7 @@ export const getAllDevicesOwnedBy = async (owner: string, configuration: Configu
};

export interface IConsumingDevice extends Device.IOnChainProperties {
offChainProperties: Device.IOffChainProperties
offChainProperties: Device.IOffChainProperties;
}

export class Entity extends Device.Entity implements IConsumingDevice {
Expand All @@ -90,7 +96,7 @@ export class Entity extends Device.Entity implements IConsumingDevice {
this.smartMeter = { address: device.smartMeter };
this.owner = { address: device.owner };
this.lastSmartMeterReadWh = Number(device.lastSmartMeterReadWh);
this.active = device.active;
this.status = Number(device.status);
this.usageType = Number(device.usageType);
this.lastSmartMeterReadFileHash = device.lastSmartMeterReadFileHash;
this.propertiesDocumentHash = device.propertiesDocumentHash;
Expand Down
Loading

0 comments on commit 47de89c

Please sign in to comment.