I have 2 types of submodules in my network.
AdhocHost which is standard definition in INET framework.
module of type IMobility with its mobility type
of type RandomWPMobility, both are standard INET modules.
I can get the location of modules of type AdhocHost by this code:
module = simulation.getModuleByPath("Mynet.host[1]");
c = MobilityAccess().get(module)->getCurrentPosition();
host[*] being of type AdhocHost.
But when I replace host[1] with blockage[1] (blockage is of type IMobility), before running simulation this error appears:
Error in module (MyMobileController) Mynet.mymobilecontroller during
network initialization: Model error: module (IMobility)mobility not
found.
The module mymobilecontroller is the module that contains this fraction of code. This module does not need to move. Its duty is just to record the location of mobile modules in the network.
What is the problem?
The 'MobilityAccess' code expects that you pass a NetworkNode to it that contains a submodule named mobility with the type IMobility. In the first case it is true (with a StandardHost) however in the second case you pass directly an module that has a type of IMobility.
Long story short, a module with a type of IMobility is meant to exist INSIDE of a network node and not at the network level.
Solution: I'm not sure what is the blockage module supposed to do, but it should NOT be a type of IMobility, instead it should be a module that contains a submodule with a type IMobility.
Related
I have folder structure like this:
> validations
> user
> user.validation.go
> address
> address.validation.go
the package name for those two file is validations
inside user.validation.go I try to use the address validation struct like this:
type UserValidation struct {
Address AddressValidation // the error says: undeclared name: AddressValidation
}
and I have tried calling package name before struct like this:
type UserValidation struct {
Address validations.AddressValidation // the error says: undeclared name: validations
}
and I have tried to import it first:
import "example/go-api/validations"
and the error says: AddressValidation not declared by package validations
You have three separate packages in each of these folders:
validations
user
address
The validations folder contains only other packages so is not able to be usefully imported; it contains no code with any exports.
The user folder also contains a package named validations this can usefully imported to access the exported UserValidation type.
The address folder also contains a package named validations this can be usefully imported to access the exported AddressValidation type.
But GoLang does not treat these as all forming a single validations package. A 'package' is a namespace, but packages with the same name are not the same namespace. They all remain separate and distinct packages (and namespaces).
If the validations package in the user folder wishes to import the validations package in the address folder it can do so but must reference the full path to that package and must alias the import since the folder name does not match the name of the package it contains:
import validations "example/go-api/validations/address"
type UserValidation struct {
Address validations.AddressValidation
}
will work just fine.
But note that since this involves an alias, that alias can be anything you like - it doesn't have to match the name of the imported package. i.e. this is just as valid:
import v "example/go-api/validations/address"
type UserValidation struct {
Address v.AddressValidation
}
If some other package in your project wishes to reference both UserValidation and AddressValidation it must import both of the separate validations packages that contain them and provide unique aliases for each:
import (
addressValidations "example/go-api/validations/address"
userValidations "example/go-api/validations/user"
)
and may then do something like:
var (
av addressValidations.AddressValidation
uv userValidations.UserValidation
)
The key to all of this is that folders are not a way of organising files within a package. A folder is a package.
Unless you have a specific reason for doing otherwise it is best to:
Name a package for the folder that contains its files
Use unique names for packages (in the same project/module)
There are occasional, valid exceptions to rule #2, e.g. where a package name makes sense in two different and mutually exclusive contexts. i.e. where no other package would never wish or need to import different packages of the same name from those different contexts.
I've yet to encounter a valid exception to rule #1. :)
Possible Alternative Approach
If you really want to keep UserValidation and AddressValidation in separate packages, you could name the packages user and address (i.e. apply rule #1: name each package for their respective folders).
Then, since the package name provides the address or user context for the symbols within them, you can rename the types to simply Validation in each case.
Your user.go code then becomes:
package user
import "example/go-api/validations/address"
type Validation struct {
Address address.Validation
}
and your address.go code:
package address
type Validation struct {}
and variables in a package that imports both user and address validations become:
import (
"example/go-api/validations/address"
"example/go-api/validations/user"
)
var (
av address.Validation
uv user.Validation
)
Caveat Coder
This is not a prescription! Without knowing more about your specific use case I have no idea whether this is the best way to skin this particular feline; it is merely an illustration of one way.
In short: use your folder/package names to help add context and meaning to the symbols exported by your packages.
In my project, I am using a wrapper structure, that is defined similar to this:
type Wrapper[T any] struct {
Foo int
Data T
}
Additionally, my chain code offers a method with the following signature
func(contract *MyContract) DoSomething() *Wrapper[mypkg.Bar]
where Bar is a simple structure defined - for example - like this:
package mypkg
struct Bar {
Foo string
Bar string
}
Anyhow, if I try to deploy my chaincode, I get the following error:
Error compiling schema for MyContract[DoSomething]. Return schema invalid. Object has no key 'Wrapper[[]<part of module name>'
Strangely, the part with Wrapper[[]<part of module name> is cropped. So only part of the module name is showing, and, as you can see, the bracketing is wrong: The second closing bracket is missing (so that is not a mistake made by me). The name of my module is the link to the GitHub repository.
I have tried to manually replace the generic type T in Wrapper with Bar by creating the structure
type WrapperBar struct {
Foo int
Data Bar
}
If I now adapt the function signature to
func(contract *MyContract) DoSomething() *WrapperBar
it works just fine. Unfortunately, I am using the structure Wrapper several times with different
type instantiations. So although creating all the types manually would be a workaround, it is obviously not a very elegant one.
Is there another workaround so that I can still use my generic Wrapper structure?
I am currently using go in version 1.18 and fabric-contract-api-go in version v1.1.1.
The Go contract-api at this time doesn't support Go Generics, the only workarounds I can suggest are the one that you have tried noted in this question or to write your chaincode without using the contract API, there is an example here https://github.com/hyperledger/fabric-samples/tree/main/chaincode/marbles02/go of an implementation that doesn't use the contract-api.
Your implemention will have to do more work in your chaincode such as providing your own method dispatching, validating and unmarshalling the input data
You could raise an issue at https://github.com/hyperledger/fabric-contract-api-go and ideally also contribute a PR that addresses this issue as I can't say when or if this would ever be supported.
I'm simulating network in Omnet++, with INET framework. I want to get the position (coordination x & y) of node. So I do this code:
cModule *host = getContainingNode(this);
IMobility *mobility = check_and_cast<IMobility *>(host->getSubmodule("mobility"));
... = mobility -> getCurrentPosition();
But, when I ran the simulation, I got this error
check_and_cast(): cannot cast nullptr to type 'inet::IMobility *'
Can you explain to me this error?
As I see, if the simulator notify that, so host->getSubmodule("mobility") is nullptr?
By the way, I have define mobilityType in the NED file and include IMobility.h
The NED code you shared shows that you have a simple module that implements the IMobility interface, while the C++ code looks like something that is inside a simple module which is INSIDE a compound module that represent the network host and this compound module also contains a separate simple module called "mobility" that implements the IMobility interface. (this is how code is implemented in INET).
You should either:
arrange your code so you have a compound module as a networkNode with several simple modules inside it (one of them is the mobility module).
if you insist having a simple module which already implements the IMobility interface (in C++) then you already have access to the position on that object using the getCurrentPosition method.
I assume (and recommend) that you co on the first route, so you should reaarange your NED file.
I have two submodules in compound module. I try to connect them using gate, but it creates this error:
Error in module(cmodule) wnetwork.host0 during network setup.
Gate 'wnetwork.host[0].gate$i[0]' is not connected to a submodule(or
internally to another gate of the same module)
My compound module code is
wirelessnode.ned:
package core;
import org.mixim.modules.power.battery.BatteryStats;
import org.mixim.modules.power.battery.SimpleBattery;
module wirelessnode
{
parameters:
volatile double Energy #unit(mW) = default(10.0mW);
double Tx_energy #unit(mW) = default(0.8mW);
double Tx_interval #unit(s) = default(0.5s);
#display("bgb=210,450,white;i=device/palm;i2=status/battery;b=40,40,rect");
submodules:
batteryStats: BatteryStats {
#display("p=110,221;i=block/table,#FF8040");
}
battery: SimpleBattery {
#display("p=101,90;i=block/plug,#FF8000");
}
}
wirelessnodehost.ned:
package core;
module wirelessnodehost extends wirelessnode
{
gates:
inout gate[];
}
wnetwork.ned:
package core;
import core.wirelessnodehost;
network wnetwork
{
parameters:
int numDevices=default(3);
submodules:
host[numDevices]: wirelessnodehost;
connections:
for i = 0..numDevices-2 {
host[i].gate++ <--> host[i+1].gate++;
}
}
How to solve this error?
If you check the error message, it says: wnetwork.host[0].gate$i[0] is not connected to a submodule (or internally to another gate of the same module). (see emphasis), so the problem is NOT that connecting the two module is wrong somehow, but instead the internals of the wirelessnodehost are incorrect.
Specifically, you are defining the wirelessnodehost as a compound module (a module built up from other modules by connecting them together, while you do not specify any submodules in it). I assume that you have some C++ code for the wirelessnodehost. In this case you must define it as simple wirelessnodehost. Only simple modules have a corresponding code and they are allowed to process the incoming messages using their code. On the other hand compound modules should always pass the incoming message to a submodule for processing, that's why the runtime complaining. You have not connected the gate internally so the runtime does not know where to pass the incoming message.
As a side note, the fact that you extend wirelessnode module (which itself should have a corresponding C++ code and should be defined as 'simple') is rather suspicious. If the code that handles the behavior of the node is implemented in the wirelessnode class, then it does not know anything about the gate that is defined in the wirelessnodehost. I would suggest to take a deeper look at the part of the OMNeT++ manual which describes the differences between simple and compound modules.
New to GoLang, coming from Delphi, C++ :
First time I tried to create my own package in Go, I followed all the instructions about how to lay out the workspace, etc, but I kept on getting a compiler error:
./myPackage.go:52: undefined: myFunc
After poking around a bit I discovered that the public access modifier in Go is achieved simply by declaring a function in upper case. Great.
But when I started experimenting with the container classes - List for starters, I discovered I had to declare a List reference return value like this:
func GetFactors(value *int64) *list.List {...
*list is in lower case.
Same when I declared a local reference to a list - I had to use:
l := list.New()
Again, lower case for list.
So, I'm confused. What is the rule? The list calls and references are obviously public, or I wouldn't be able to call/use them - so why are they in lower case?
In this case, list is the name of the package, which you are importing via import "container/list", and its public members are upper case, like List.
The rule is that public functions, types, etc., should be upper case.
You can alias imported packages however you want, but by default it is just the name of the last part of the package path--in this case, list.
Update: It's not the last part of the package path. It's the actual package name (which is often the same thing).
Note: starting Go 1.5 (Q2/Q3 2015), you will get "protected" import as well (named "internal")!
See Go 1.4 doc:
Go's package system makes it easy to structure programs into components with clean boundaries, but there are only two forms of access: local (unexported) and global (exported).
Sometimes one wishes to have components that are not exported, for instance to avoid acquiring clients of interfaces to code that is part of a public repository but not intended for use outside the program to which it belongs.
The Go language does not have the power to enforce this distinction, but as of Go 1.4 the go command introduces a mechanism to define "internal" packages that may not be imported by packages outside the source subtree in which they reside.
To create such a package, place it in a directory named internal or in a subdirectory of a directory named internal.
When the go command sees an import of a package with internal in its path, it verifies that the package doing the import is within the tree rooted at the parent of the internal directory.
For example, a package .../a/b/c/internal/d/e/f can be imported only by code in the directory tree rooted at .../a/b/c.
It cannot be imported by code in .../a/b/g or in any other repository.
For Go 1.4, the internal package mechanism is enforced for the main Go repository;
from 1.5 and onward it will be enforced for any repository.
Note: the Go Spec for package name don't mention that a package name is always in lowercase.
It only state that its name is represented by an identifier, which is composed of a collection of "letter".
This thread does clarify:
Package names can be anything, you can start them with an uppercase letter if you want to.
But the convention is all lowercase, which I guess saves you the hassle of typing an uppercase letter.
The uppercase/lowercase exportability isn't really relevant to packages since you can't have a private package.
Once you know that, it is easier to recognize:
list.New() for a constructor (always at the package level, to build an initialized instance of a type), like os.NewFile(),
list.List for a struct type of the package list (the other struct type of that same package being list.Element).