/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import "github.com/deckarep/golang-set"

// FastLineInventoryAndStatusDataPart2ClassID is the 16-bit ID for the OMCI
// Managed entity FAST line inventory and status data part 2
const FastLineInventoryAndStatusDataPart2ClassID ClassID = ClassID(436)

var fastlineinventoryandstatusdatapart2BME *ManagedEntityDefinition

// FastLineInventoryAndStatusDataPart2 (class ID #436)
//	This ME contains part 3 of the FAST line inventory and status data with attributes specific to
//	[ITU T G.997.2]. The ONU automatically creates or deletes an instance of this ME upon the
//	creation or deletion of a PPTP xDSL UNI part 1.
//
//	Relationships
//		This is one of the status data MEs associated with an xDSL UNI. It is required only if FAST is
//		supported by the PPTP. The ONU automatically creates or deletes an instance of this ME upon
//		creation or deletion of a PPTP xDSL UNI part 1 that supports these attributes.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
//			(mandatory) (2-bytes)
//
//		Date_Time_Stamping Of Last Successful Downstream Fra Operation Stamp_Frads
//			(R) (optional) (7 bytes)
//
//		Date_Time_Stamping Of Last Successful Upstream Fra Operation Stamp_Fraus
//			Date/time-stamping of last successful upstream FRA operation (STAMP-FRAus): This parameter
//			reports the date/time of the last successful FTU-O initiated FRA execution that has modified the
//			bits allocation. See clause 7.10.14.6 of [ITUT-G.997.2]. The format of this parameter is the
//			same as STAMPTESTNE. (R) (optional) (7 bytes)
//
//		Date_Time_Stamping Of Last Successful Downstream Rpa Operation Stamp_Rpads
//			Date/time-stamping of last successful downstream RPA operation (STAMP-RPAds): This parameter
//			reports the date/time of the last successful FTU-R initiated RPA execution that has modified the
//			bits allocation for the RMC. See clause-7.10.14.7 of [ITU-T G.997.2]. The format of this
//			parameter is the same as STAMP-TEST-NE. (R) (optional) (7 bytes)
//
//		Date_Time_Stamping Of Last Successful Upstream Rpa Operation Stamp_Rpaus
//			Date/time-stamping of last successful upstream RPA operation (STAMP-RPAus): This parameter
//			reports the date/time of the last successful FTU-O initiated RPA execution that has modified the
//			bits allocation for the RMC. See clause-7.10.14.8 of [ITU-T G.997.2]. The format of this
//			parameter is the same as STAMP-TEST-NE. (R) (optional) (7 bytes)
//
//		Date_Time_Stamping Of Last Successful Downstream Tiga Operation Stamp_Tiga
//			Date/time-stamping of last successful downstream TIGA operation (STAMP-TIGA): This parameter
//			reports the date/time of the last successful FTU-O initiated TIGA execution. See clause
//			7.10.14.9 of [ITU-T G.997.2]. The format of this parameter is the same as STAMP-TEST-NE. (R)
//			(optional) (7 bytes)
//
type FastLineInventoryAndStatusDataPart2 struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	fastlineinventoryandstatusdatapart2BME = &ManagedEntityDefinition{
		Name:    "FastLineInventoryAndStatusDataPart2",
		ClassID: 436,
		MessageTypes: mapset.NewSetWith(
			Get,
		),
		AllowedAttributeMask: 0xf800,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1: MultiByteField("DateTimeStampingOfLastSuccessfulDownstreamFraOperationStampFrads", OctetsAttributeType, 0x8000, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 1),
			2: MultiByteField("DateTimeStampingOfLastSuccessfulUpstreamFraOperationStampFraus", OctetsAttributeType, 0x4000, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 2),
			3: MultiByteField("DateTimeStampingOfLastSuccessfulDownstreamRpaOperationStampRpads", OctetsAttributeType, 0x2000, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 3),
			4: MultiByteField("DateTimeStampingOfLastSuccessfulUpstreamRpaOperationStampRpaus", OctetsAttributeType, 0x1000, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 4),
			5: MultiByteField("DateTimeStampingOfLastSuccessfulDownstreamTigaOperationStampTiga", OctetsAttributeType, 0x0800, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 5),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
	}
}

// NewFastLineInventoryAndStatusDataPart2 (class ID 436) creates the basic
// Managed Entity definition that is used to validate an ME of this type that
// is received from or transmitted to the OMCC.
func NewFastLineInventoryAndStatusDataPart2(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*fastlineinventoryandstatusdatapart2BME, params...)
}
